Albert
Loading...
Searching...
No Matches
backgroundexecutor.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2024 Manuel Schneider
2// SPDX-License-Identifier: MIT
3
4#pragma once
5#include <QFutureWatcher>
6#include <QtConcurrent>
7#include <albert/logging.h>
8#include <chrono>
9#include <functional>
10
11namespace albert
12{
13
18template<typename T> class BackgroundExecutor
19{
20public:
25 std::function<T(const bool &abort)> parallel;
26
31 std::function<void(T && results)> finish;
32
34 std::chrono::milliseconds runtime;
35
36private:
37 QFutureWatcher<T> future_watcher_;
38 bool rerun_ = false;
39
40 void onFinish()
41 {
42 if (rerun_){ // discard and rerun
43 rerun_ = false;
44 run();
45 }
46 else
47 {
48 try {
49 finish(std::move(future_watcher_.future().takeResult()));
50 } catch (const std::exception &e) {
51 WARN << "Exception in BackgroundExecutor::finish"
52 << QString::fromStdString(e.what());
53 } catch (...) {
54 WARN << "Unknown exception in BackgroundExecutor::finish.";
55 }
56 }
57 }
58
59 T run_(const bool &abort)
60 {
61 try {
62 auto start = std::chrono::system_clock::now();
63 T ret = parallel(abort);
64 auto end = std::chrono::system_clock::now();
65 runtime = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
66 return ret;
67 } catch (const std::exception &e) {
68 WARN << "Exception in BackgroundExecutor::parallel" << QString::fromStdString(e.what());
69 } catch (...) {
70 WARN << "Unknown exception in BackgroundExecutor::parallel.";
71 }
72 return {};
73 }
74
75public:
77 QObject::connect(&future_watcher_, &QFutureWatcher<T>::finished, [this](){onFinish();});
78 };
79
81 rerun_ = false;
82 if (isRunning()){
83 WARN << "Busy wait for BackgroundExecutor task. Abortion handled correctly?";
84 auto start = std::chrono::system_clock::now();
85 future_watcher_.waitForFinished();
86 auto end = std::chrono::system_clock::now();
87 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
88 WARN << QStringLiteral("Busy waited for %1 ms.").arg(duration.count());
89 }
90 };
91
95 void run() {
96 if (future_watcher_.isRunning())
97 rerun_ = true;
98 else
99 future_watcher_.setFuture(QtConcurrent::run(&BackgroundExecutor<T>::run_, this, rerun_));
100 }
101
104 bool isRunning() const { return future_watcher_.isRunning(); }
105};
106
107}
Provides a lean interface for recurring indexing tasks.
Definition backgroundexecutor.h:19
bool isRunning() const
Returns true if the asynchronous computation is currently running; otherwise returns false.
Definition backgroundexecutor.h:104
~BackgroundExecutor()
Definition backgroundexecutor.h:80
std::chrono::milliseconds runtime
The runtime of the last execution of parallel.
Definition backgroundexecutor.h:34
std::function< void(T &&results)> finish
The results handler.
Definition backgroundexecutor.h:31
std::function< T(const bool &abort)> parallel
The task that should be executed in background.
Definition backgroundexecutor.h:25
void run()
Run or schedule a rerun of the task.
Definition backgroundexecutor.h:95
BackgroundExecutor()
Definition backgroundexecutor.h:76
#define WARN
Creates a log object (level warning) you can use to pipe text into (<<).
Definition logging.h:20
Definition action.h:10