1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQMLTHREAD_P_H
5#define QQMLTHREAD_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18
19#include <QtCore/qglobal.h>
20
21#include <private/qintrusivelist_p.h>
22
23QT_BEGIN_NAMESPACE
24
25class QThread;
26class QMutex;
27
28class QQmlThreadPrivate;
29class QQmlThread
30{
31public:
32 QQmlThread();
33 virtual ~QQmlThread();
34
35 void startup();
36 void shutdown();
37 bool isShutdown() const;
38
39 QMutex &mutex();
40 void lock();
41 void unlock();
42 void wakeOne();
43 void wait();
44
45 QThread *thread() const;
46 bool isThisThread() const;
47
48 // Synchronously invoke a method in the thread
49 template<typename Method, typename ...Args>
50 void callMethodInThread(Method &&method, Args &&...args);
51
52 // Synchronously invoke a method in the main thread. If the main thread is
53 // blocked in a callMethodInThread() call, the call is made from within that
54 // call.
55 template<typename Method, typename ...Args>
56 void callMethodInMain(Method &&method, Args &&...args);
57
58 // Asynchronously invoke a method in the thread.
59 template<typename Method, typename ...Args>
60 void postMethodToThread(Method &&method, Args &&...args);
61
62 // Asynchronously invoke a method in the main thread.
63 template<typename Method, typename ...Args>
64 void postMethodToMain(Method &&method, Args &&...args);
65
66 void waitForNextMessage();
67
68private:
69 friend class QQmlThreadPrivate;
70
71 struct Message {
72 Message() : next(nullptr) {}
73 virtual ~Message() {}
74 Message *next;
75 virtual void call(QQmlThread *) = 0;
76 };
77 template<typename Method, typename ...Args>
78 Message *createMessageFromMethod(Method &&method, Args &&...args);
79 void internalCallMethodInThread(Message *);
80 void internalCallMethodInMain(Message *);
81 void internalPostMethodToThread(Message *);
82 void internalPostMethodToMain(Message *);
83 QQmlThreadPrivate *d;
84};
85
86namespace QtPrivate {
87template <typename> struct member_function_traits;
88
89template <typename Return, typename Object, typename... Args>
90struct member_function_traits<Return (Object::*)(Args...)>
91{
92 using class_type = Object;
93};
94}
95
96template<typename Method, typename ...Args>
97QQmlThread::Message *QQmlThread::createMessageFromMethod(Method &&method, Args &&...args)
98{
99 struct I : public Message {
100 Method m;
101 std::tuple<std::decay_t<Args>...> arguments;
102 I(Method &&method, Args&& ...args) : m(std::forward<Method>(method)), arguments(std::forward<Args>(args)...) {}
103 void call(QQmlThread *thread) override {
104 using class_type = typename QtPrivate::member_function_traits<Method>::class_type;
105 class_type *me = static_cast<class_type *>(thread);
106 std::apply(m, std::tuple_cat(std::make_tuple(me), arguments));
107 }
108 };
109 return new I(std::forward<Method>(method), std::forward<Args>(args)...);
110}
111
112template<typename Method, typename ...Args>
113void QQmlThread::callMethodInMain(Method &&method, Args&& ...args)
114{
115 Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...);
116 internalCallMethodInMain(m);
117}
118
119template<typename Method, typename ...Args>
120void QQmlThread::callMethodInThread(Method &&method, Args&& ...args)
121{
122 Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...);
123 internalCallMethodInThread(m);
124}
125
126template<typename Method, typename ...Args>
127void QQmlThread::postMethodToThread(Method &&method, Args&& ...args)
128{
129 Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...);
130 internalPostMethodToThread(m);
131}
132
133template<typename Method, typename ...Args>
134void QQmlThread::postMethodToMain(Method &&method, Args&& ...args)
135{
136 Message *m = createMessageFromMethod(std::forward<Method>(method), std::forward<Args>(args)...);
137 internalPostMethodToMain(m);
138}
139
140QT_END_NAMESPACE
141
142#endif // QQMLTHREAD_P_H
143

source code of qtdeclarative/src/qml/qml/ftw/qqmlthread_p.h