#include "FutureScheduler.h" FutureScheduler::FutureScheduler(QObject *parent) : QObject(parent), Alive(0), Stopping(false) { } FutureScheduler::~FutureScheduler() { shutdownWaitForFinished(); } void FutureScheduler::shutdownWaitForFinished() noexcept { QMutexLocker locker(&Mutex); Stopping = true; while (Alive > 0) { Condition.wait(&Mutex); } } QPair> FutureScheduler::run(std::function function) noexcept { return execute([this, function](QFutureWatcher *) { return QtConcurrent::run([this, function] { try { function(); } catch (const std::exception &exception) { qWarning() << "Exception thrown from async function: " << exception.what(); } done(); }); }); } QPair> FutureScheduler::run(std::function function, const QJSValue &callback) { if (!callback.isCallable()) { throw std::runtime_error("js callback must be callable"); } return execute([this, function, callback](QFutureWatcher *watcher) { connect(watcher, &QFutureWatcher::finished, [watcher, callback] { QJSValue(callback).call(watcher->future().result()); }); return QtConcurrent::run([this, function] { QJSValueList result; try { result = function(); } catch (const std::exception &exception) { qWarning() << "Exception thrown from async function: " << exception.what(); } done(); return result; }); }); } bool FutureScheduler::add() noexcept { QMutexLocker locker(&Mutex); if (Stopping) { return false; } ++Alive; return true; } void FutureScheduler::done() noexcept { { QMutexLocker locker(&Mutex); --Alive; } Condition.wakeAll(); }