blob: d8f489a3b825e2731f6d7a138827fea1cd9b5451 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
#ifndef ASYNC_JOB_839147839170432143214321
#define ASYNC_JOB_839147839170432143214321
#include <list>
#include <functional>
#include "thread.h"
#include "scope_guard.h"
namespace zen
{
//run a job in an async thread, but process result on GUI event loop
class AsyncTasks
{
public:
AsyncTasks() {}
template <class Fun, class Fun2>
void add(Fun runAsync, Fun2 evalOnGui)
//equivalent to "evalOnGui(runAsync())"
// -> runAsync: the usual thread-safety requirements apply!
// -> evalOnGui: no thread-safety concerns, but must only reference variables with greater-equal lifetime than the AsyncTask instance!
{
tasks.push_back(zen::runAsync([=]() -> std::function<void()>
{
auto result = runAsync();
return [=]{ evalOnGui(result); };
}));
}
template <class Fun, class Fun2>
void add2(Fun runAsync, Fun2 evalOnGui) //for evalOnGui taking no parameters
{
tasks.push_back(zen::runAsync([runAsync, evalOnGui]() -> std::function<void()> { runAsync(); return [evalOnGui]{ evalOnGui(); }; }));
}
void evalResults() //call from gui thread repreatedly
{
if (!inRecursion) //prevent implicit recursion, e.g. if we're called from an idle event and spawn another one via the callback below
{
inRecursion = true;
ZEN_ON_SCOPE_EXIT(inRecursion = false);
tasks.remove_if([](std::future<std::function<void()>>& ft) -> bool
{
if (isReady(ft))
{
(ft.get())();
return true;
}
return false;
});
}
}
bool empty() const { return tasks.empty(); }
private:
AsyncTasks (const AsyncTasks&) = delete;
AsyncTasks& operator=(const AsyncTasks&) = delete;
bool inRecursion = false;
std::list<std::future<std::function<void()>>> tasks;
};
}
#endif //ASYNC_JOB_839147839170432143214321
|