4
1
mirror of https://github.com/QuasarApp/Heart.git synced 2025-05-12 17:39:42 +00:00

added async class

This commit is contained in:
Andrei Yankovich 2020-11-29 23:31:55 +03:00
parent d6aa8ba383
commit 4f3e6b2ea1
5 changed files with 199 additions and 227 deletions

@ -0,0 +1,47 @@
#include "async.h"
#include <QCoreApplication>
#include <QDateTime>
// 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; \
namespace QH {
Async::Async(QObject *ptr):
QObject(ptr) {
}
void Async::asyncLauncher(std::function<bool ()> job,
bool *resultOfWork,
bool *endOfWork) const {
bool result = job();
if (resultOfWork)
*resultOfWork = result;
if (endOfWork) {
*endOfWork = true;
}
}
bool Async::waitFor(bool *condition, int timeout) const {
if (!condition)
return false;
waitPrivate(*condition, timeout)
}
bool Async::waitFor(const std::function<bool ()> &condition, int timeout) const {
waitPrivate(condition(), timeout)
}
}

@ -0,0 +1,97 @@
#ifndef ASYNC_H
#define ASYNC_H
#include <QObject>
#include <functional>
#include "config.h"
namespace QH {
/**
* @brief The Async class This is bandele of async templates and async wrapers.
* @note If you use this object then you do not need include QObject becouse this class include the QObject class.
* Do not forgae the Q_OBJECT mactoss.
*/
class Async: public QObject {
Q_OBJECT
protected:
Async(QObject* ptr = nullptr);
/**
* @brief asyncLauncher This is base async launcher method for move jobs to new thread.
* @param job This is job to do.
* @param resultOfWork This is pointer of bool value of a result of the job method.
* @note If you want to disable check results just use nullptr value.
* @param endOfWork This is pointer to bool value. If balue of this method changed to true then the hob method has ben finished.
* For check result of the job dunction use the resultOfWork option.
*
* Example of use:
*
* Async Await:
* \code{cpp}
*
* auto job = [](){
* ...
* return true;
* }
* bool invoke = QMetaObject::invokeMethod(this,
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(std::function<bool()>, job),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
if (!invoke) {
return false;
}
if (!waitFor(&workOfEnd)) {
return false;
}
return workResult;
* \endcode
*
*
* Async:
* \code{cpp}
*
* auto job = [](){
* ...
* return true;
* }
* bool invoke = QMetaObject::invokeMethod(this,
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(std::function<bool()>, job));
return invoke;
* \endcode
*/
void asyncLauncher(std::function<bool()> job,
bool* resultOfWork = nullptr,
bool* endOfWork = nullptr) const;
/**
* @brief waitFor This is base wait function.
* @param condition This is pointer to awaiting boolean variable.
* @param timeout This is maximu time for wait. By default this value equals WAIT_TIME it is 30000 msec.
* @return true if condition is true.
*/
bool waitFor(bool* condition, int timeout = WAIT_TIME) const;
/**
* @brief waitFor This is base wait function.
* @param condition This is lambda method with condition results.
* @param timeout This is maximu time for wait. By default this value equals WAIT_TIME it is 30000 msec.
* @return true if condition is true.
*/
bool waitFor(const std::function<bool()> &condition, int timeout = WAIT_TIME) const;
};
}
Q_DECLARE_METATYPE(std::function<bool()>)
#endif // ASYNC_H

@ -46,9 +46,9 @@ void SqlDBCache::globalUpdateDataBasePrivate(qint64 currentTime) {
bool saveResult = false;
if (it.key() == MemberType::Insert) {
saveResult = _writer->insertObjectWithWait(obj);
saveResult = _writer->insertObject(obj, true);
} else {
saveResult = _writer->updateObjectWithWait(obj);
saveResult = _writer->updateObject(obj, true);
}
if (!saveResult ) {

@ -185,7 +185,7 @@ QVariantMap SqlDBWriter::defaultInitPararm() const {
}
SqlDBWriter::SqlDBWriter(QObject* ptr):
QObject(ptr) {
Async(ptr) {
}
bool SqlDBWriter::initDb(const QString &initDbParams) {
@ -201,17 +201,20 @@ bool SqlDBWriter::initDb(const QString &initDbParams) {
}
bool SqlDBWriter::initDb(const QVariantMap &params) {
if (QThread::currentThread() == thread()) {
auto handleInitDb = [&params, this]() {
return SqlDBWriter::initDb(params);
};
if (QThread::currentThread() == thread()) {
return handleInitDb();
}
bool workOfEnd = false, workResult = false;
bool invockeResult = QMetaObject::invokeMethod(this,
"handleInitDb",
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(const QVariantMap &, params),
Q_ARG(decltype (handleInitDb), handleInitDb),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
@ -232,18 +235,21 @@ bool SqlDBWriter::isValid() const {
bool SqlDBWriter::getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) {
auto getAll = [&templateObject, &result, this]() {
return SqlDBWriter::selectQuery(templateObject, result);
};
if (QThread::currentThread() == thread()) {
return SqlDBWriter::selectQuery(templateObject, result, nullptr, nullptr);
return getAll();
}
bool workOfEnd = false, workResult = false;
bool invockeResult = QMetaObject::invokeMethod(this,
"selectQuery",
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, &templateObject),
Q_ARG(QList<const QH::PKG::DBObject *> *, &result),
Q_ARG(decltype (getAll), getAll),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
@ -259,8 +265,12 @@ bool SqlDBWriter::getAllObjects(const DBObject &templateObject, QList<const DBO
}
bool SqlDBWriter::updateObject(const DBObject* ptr, bool wait) {
auto updateQueryWraper = [ptr, this]() {
return updateQuery(ptr);
};
if (QThread::currentThread() == thread()) {
return updateQuery(ptr, nullptr, nullptr);
return updateQueryWraper();
}
auto clone = ptr->cloneRaw();
@ -268,9 +278,9 @@ bool SqlDBWriter::updateObject(const DBObject* ptr, bool wait) {
bool workOfEnd = false, workResult = false;
bool invockeResult = QMetaObject::invokeMethod(this,
"updateQuery",
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, clone),
Q_ARG(decltype (updateQueryWraper), updateQueryWraper),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
@ -291,17 +301,21 @@ bool SqlDBWriter::updateObject(const DBObject* ptr, bool wait) {
}
bool SqlDBWriter::deleteObject(const DBObject* ptr, bool wait) {
auto deleteQueryWraper = [ptr, this]() {
return deleteQuery(ptr);
};
if (QThread::currentThread() == thread()) {
return deleteQuery(ptr, nullptr, nullptr);
return deleteQueryWraper();
}
bool workOfEnd = false, workResult = false;
auto clone = ptr->cloneRaw();
bool invockeResult = QMetaObject::invokeMethod(this,
"deleteQuery",
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, clone),
Q_ARG(decltype (deleteQueryWraper), deleteQueryWraper),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
delete clone;
@ -322,17 +336,21 @@ bool SqlDBWriter::deleteObject(const DBObject* ptr, bool wait) {
bool SqlDBWriter::insertObject(const DBObject *saveObject, bool wait) {
auto insertQueryWraper = [saveObject, this]() {
return insertQuery(saveObject);
};
if (QThread::currentThread() == thread()) {
return insertQuery(saveObject, nullptr, nullptr);
return insertQueryWraper();
}
bool workOfEnd = false, workResult = false;
auto clone = saveObject->cloneRaw();
bool invockeResult = QMetaObject::invokeMethod(this,
"insertQuery",
"asyncLauncher",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, clone),
Q_ARG(decltype (insertQueryWraper), insertQueryWraper),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
delete clone;
@ -352,113 +370,6 @@ bool SqlDBWriter::insertObject(const DBObject *saveObject, bool wait) {
}
bool SqlDBWriter::waitFor(bool *condition, int timeout) const {
auto curmsec = QDateTime::currentMSecsSinceEpoch() + timeout;
while (curmsec > QDateTime::currentMSecsSinceEpoch() && !*condition) {
QCoreApplication::processEvents();
}
QCoreApplication::processEvents();
return *condition;
}
void SqlDBWriter::handleInitDb(const QVariantMap &params, bool *resultOfWork, bool *endOfWork) {
bool work = initDbPrivate(params);
if (resultOfWork) {
*resultOfWork = work;
}
if (endOfWork) {
*endOfWork = true;
}
}
bool SqlDBWriter::updateObjectWithWait(const DBObject *saveObject) {
if (QThread::currentThread() == thread()) {
return SqlDBWriter::updateObject(saveObject);
}
bool workOfEnd = false, workResult = false;
bool invoke = QMetaObject::invokeMethod(this,
"handleUpdateObject",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, saveObject),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
if (!invoke) {
QuasarAppUtils::Params::log("handleUpdateObject not invokecd", QuasarAppUtils::Debug);
return false;
}
if (!waitFor(&workOfEnd)) {
return false;
}
return workResult;
}
bool SqlDBWriter::insertObjectWithWait(const DBObject *saveObject) {
if (QThread::currentThread() == thread()) {
return SqlDBWriter::insertObject(saveObject);
}
bool workOfEnd = false, workResult = false;
bool invoke = QMetaObject::invokeMethod(this,
"handleInsertObject",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, saveObject),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
if (!invoke) {
QuasarAppUtils::Params::log("handleInsertObject not invokecd", QuasarAppUtils::Debug);
return false;
}
if (!waitFor(&workOfEnd)) {
return false;
}
return workResult;
}
bool SqlDBWriter::deleteObjectWithWait(const DBObject *deleteObject) {
if (QThread::currentThread() == thread()) {
return SqlDBWriter::deleteObject(deleteObject);
}
bool workOfEnd = false, workResult = false;
bool invoke = QMetaObject::invokeMethod(this,
"handleDeleteObject",
Qt::QueuedConnection,
Q_ARG(const QH::PKG::DBObject *, deleteObject),
Q_ARG(bool *, &workResult),
Q_ARG(bool *, &workOfEnd));
if (!invoke) {
QuasarAppUtils::Params::log("handleDeleteObject not invokecd", QuasarAppUtils::Debug);
return false;
}
if (!waitFor(&workOfEnd)) {
return false;
}
return workResult;
}
void SqlDBWriter::setSQLSources(const QStringList &list) {
_SQLSources = list;
}
@ -471,8 +382,7 @@ SqlDBWriter::~SqlDBWriter() {
db.close();
}
bool SqlDBWriter::insertQuery(const DBObject* ptr,
bool *workResult, bool *workOfEnd) const {
bool SqlDBWriter::insertQuery(const DBObject* ptr) const {
if (!ptr)
return false;
@ -484,20 +394,11 @@ bool SqlDBWriter::insertQuery(const DBObject* ptr,
auto cb = [](){return true;};
bool work = workWithQuery(q, prepare, cb);
if (workResult)
*workResult = work;
if (workOfEnd) {
*workOfEnd = true;
}
return work;
return workWithQuery(q, prepare, cb);
}
bool SqlDBWriter::selectQuery(const DBObject& requestObject,
QList<const DBObject *> &result,
bool *workResult, bool *workOfEnd) {
QList<const DBObject *> &result) {
QSqlQuery q(db);
auto prepare = [&requestObject](QSqlQuery&q) {
@ -541,19 +442,10 @@ bool SqlDBWriter::selectQuery(const DBObject& requestObject,
return result.size();
};
bool work = workWithQuery(q, prepare, cb);
if (workResult)
*workResult = work;
if (workOfEnd) {
*workOfEnd = true;
}
return work;
return workWithQuery(q, prepare, cb);
}
bool SqlDBWriter::deleteQuery(const DBObject *deleteObject,
bool *workResult, bool *workOfEnd) const {
bool SqlDBWriter::deleteQuery(const DBObject *deleteObject) const {
if (!deleteObject)
return false;
@ -565,21 +457,13 @@ bool SqlDBWriter::deleteQuery(const DBObject *deleteObject,
auto cb = []() -> bool {
return true;
};
};
bool work = workWithQuery(q, prepare, cb);
if (workResult)
*workResult = work;
if (workOfEnd) {
*workOfEnd = true;
}
return work;
return workWithQuery(q, prepare, cb);
}
bool SqlDBWriter::updateQuery(const DBObject *ptr,
bool *workResult, bool *workOfEnd) const {
bool SqlDBWriter::updateQuery(const DBObject *ptr) const {
if (!ptr)
return false;
@ -591,15 +475,7 @@ bool SqlDBWriter::updateQuery(const DBObject *ptr,
auto cb = [](){return true;};
bool work = workWithQuery(q, prepare, cb);
if (workResult)
*workResult = work;
if (workOfEnd) {
*workOfEnd = true;
}
return work;
return workWithQuery(q, prepare, cb);
}
bool SqlDBWriter::workWithQuery(QSqlQuery &q,

@ -12,6 +12,7 @@
#include <QSqlDatabase>
#include <QDir>
#include <QSqlQuery>
#include "async.h"
#include "heart_global.h"
#include "config.h"
#include "iobjectprovider.h"
@ -32,7 +33,7 @@ namespace QH {
* For initialize a custom database driver you need to set an own params see the SqlDBWriter::initDb metthod.
* This class work only on single thread. For change working thread use the Qt method moveToThread.
*/
class HEARTSHARED_EXPORT SqlDBWriter : public QObject, public iObjectProvider
class HEARTSHARED_EXPORT SqlDBWriter : public Async, public iObjectProvider
{
Q_OBJECT
public:
@ -76,34 +77,8 @@ public:
*/
QString databaseLocation() const;
/**
* @brief updateObjectWithWait this method is wraper of the updateObject method with waiting of works result.
* @note This method stop current thread while the request is not finished.
* @param updateObject This is pointer to the update object.
* @return true if function finished successful.
*/
bool updateObjectWithWait(const PKG::DBObject* updateObject);
/**
* @brief insertObjectWithWait this method is wraper of the insertObject method with waiting of works result.
* @note This method stop current thread while the request is not finished.
* @param inserObject This is pointer to the insert object.
* @return true if function finished successful.
*/
bool insertObjectWithWait(const PKG::DBObject* inserObject);
/**
* @brief deleteObjectWithWait this method is wraper of the deleteObject method with waiting of works result.
* @note This method stop current thread while the request is not finished.
* @param deleteObject This is pointer to the saved object.
* @return true if function finished successful
*/
bool deleteObjectWithWait(const PKG::DBObject* deleteObject);
virtual ~SqlDBWriter() override;
protected slots:
/**
* @brief updateQuery This method execute update query of object.
* For more Information see DBObject::prepareUpdateQuery.
@ -112,9 +87,7 @@ protected slots:
* @param endOfWork This wariable set true when the SqlDBWriter::saveObject is finished.
* @return true if function finished seccussful
*/
virtual bool updateQuery(const QH::PKG::DBObject *ptr,
bool * resultOfWork,
bool * endOfWork) const;
virtual bool updateQuery(const QH::PKG::DBObject *ptr) const;
/**
* @brief selectQuery generate select query to database from parameters.
@ -125,9 +98,7 @@ protected slots:
* @return true if all goodelse false
*/
virtual bool selectQuery(const QH::PKG::DBObject &requestObject,
QList<const QH::PKG::DBObject *> &result,
bool * resultOfWork,
bool * endOfWork);
QList<const QH::PKG::DBObject *> &result);
/**
* @brief deleteQuery This method prepare the delete object query.
@ -136,9 +107,7 @@ protected slots:
* @param endOfWork This wariable set true when the SqlDBWriter::selectQuery is finished.
* @return true if query generated successful.
*/
virtual bool deleteQuery(const QH::PKG::DBObject *deleteObject,
bool * resultOfWork,
bool * endOfWork) const;
virtual bool deleteQuery(const QH::PKG::DBObject *deleteObject) const;
/**
* @brief insertQuery This method prepare the insert object query.
@ -147,19 +116,10 @@ protected slots:
* @param endOfWork This wariable set true when the SqlDBWriter::selectQuery is finished.
* @return true if query generated successful.
*/
virtual bool insertQuery(const QH::PKG::DBObject *insertObject,
bool * resultOfWork = nullptr,
bool * endOfWork = nullptr) const;
virtual bool insertQuery(const QH::PKG::DBObject *insertObject) const;
/**
* @brief handleInitDb This method invoke initDb on own thread
* @note This method stop current thread while the request is not finished.
* @param params This is input parameters data. for more information see the SqlDBWriter::defaultInitPararm method.
* @param resultOfWork This is bool variable contais result of work a SqlDBWriter::saveObject method.
* @param endOfWork This wariable set true when the SqlDBWriter::saveObject is finished.
*/
virtual void handleInitDb(const QVariantMap &params,
bool *resultOfWork, bool *endOfWork);
protected slots:
protected:
@ -212,14 +172,6 @@ protected:
*/
virtual QVariantMap defaultInitPararm() const;
/**
* @brief waitFor - The base wait function.
* @param condition - condition for wait
* @param timeout - maximu time for wait. By default this value equals WAIT_TIME it is 30000 msec.
* @return true if condition is true.
*/
bool waitFor(bool* condition, int timeout = WAIT_TIME) const;
QSqlDatabase db;
private: