-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathQtPostTask.h
93 lines (79 loc) · 2.47 KB
/
QtPostTask.h
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <future>
#include <vector>
#include <memory>
#include <QThread>
// Encapsulates context information for asynchronous calls.
struct AsyncCallContext
{
std::string file;
int line;
AsyncCallContext(const std::string &file, int line) : file(file), line(line) {}
};
// Manages a stack of asynchronous call contexts.
class AsyncCallContextStack : public std::vector<std::unique_ptr<AsyncCallContext>>
{
public:
~AsyncCallContextStack()
{
clear(); // unique_ptr handles memory deallocation automatically.
}
};
// Global stack for managing asynchronous call contexts.
static AsyncCallContextStack asyncCallContextStack;
// Retrieves the current stack of asynchronous call contexts.
const AsyncCallContextStack *GetAsyncCallContextStack()
{
return &asyncCallContextStack;
}
// Pushes a new context onto the stack.
static void PushAsyncCallContext(const std::string &file, int line)
{
asyncCallContextStack.emplace_back(std::make_unique<AsyncCallContext>(file, line));
}
// Pops the last context from the stack.
static void PopAsyncCallContext()
{
asyncCallContextStack.pop_back();
}
// Implementation for posting a task to the Qt event loop.
std::future<void> PostQtTaskImpl(std::function<void()> task, const std::string &file, int line)
{
auto promise = std::make_shared<std::promise<void>>();
auto executor = [task, promise, file, line]() {
PushAsyncCallContext(file, line);
task();
PopAsyncCallContext();
promise->set_value();
};
QMetaObject::invokeMethod(qApp, executor, Qt::QueuedConnection);
return promise->get_future();
}
// Executes a task synchronously or posts it asynchronously depending on the thread context.
std::future<void> ExecOrPostQtTask(std::function<void()> task, const std::string &file, int line)
{
if (QThread::currentThread() == qApp->thread())
{
task();
std::promise<void> promise;
promise.set_value();
return promise.get_future();
}
else
{
return PostQtTaskImpl(task, file, line);
}
}
// Functor to manage asynchronous Qt calls with contextual information.
class QtAsyncCall
{
private:
using CallImpl = std::future<void> (*)(std::function<void()>, const std::string &, int);
std::string file;
int line;
CallImpl impl;
public:
QtAsyncCall(const char *file, int line, CallImpl impl) : file(file), line(line), impl(impl) {}
std::future<void> operator()(std::function<void()> task) const { return impl(task, file, line); }
};
// Macro to simplify posting tasks with context.
#define QtPostTask QtAsyncCall(__FILE__, __LINE__, &PostQtTaskImpl)