DtkCore
DTK Core module
dthreadutils.h
1/*
2 * Copyright (C) 2020 ~ 2020 Deepin Technology Co., Ltd.
3 *
4 * Author: zccrs <[email protected]>
5 *
6 * Maintainer: zccrs <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21#ifndef DTHREADUTILS_H
22#define DTHREADUTILS_H
23
24#include <dtkcore_global.h>
25#include <QObject>
26#include <QSemaphore>
27#include <QThread>
28#include <QCoreApplication>
29#include <QPointer>
30#include <QDebug>
31
32DCORE_BEGIN_NAMESPACE
33
34namespace DThreadUtil {
35typedef std::function<void()> FunctionType;
36
37class LIBDTKCORESHARED_EXPORT FunctionCallProxy : public QObject
38{
39 Q_OBJECT
40public:
41 explicit FunctionCallProxy(QThread *thread);
42
43 static void proxyCall(QSemaphore *s, QThread *thread, QObject *target, FunctionType fun);
44
45Q_SIGNALS:
46 void callInLiveThread(QSemaphore *s, QPointer<QObject> target, FunctionType *func);
47};
48
49template <typename ReturnType>
50class LIBDTKCORESHARED_EXPORT _TMP
51{
52public:
53 inline static ReturnType runInThread(QSemaphore *s, QThread *thread, QObject *target, std::function<ReturnType()> fun)
54 {
55 ReturnType result;
56 FunctionType proxyFun = [&result, &fun] () {
57 result = fun();
58 };
59
60 FunctionCallProxy::proxyCall(s, thread, target, proxyFun);
61 return result;
62 }
63
64 template <typename T>
65 inline static typename std::enable_if<!std::is_base_of<QObject, T>::value, ReturnType>::type
66 runInThread(QSemaphore *s, QThread *thread, T *, std::function<ReturnType()> fun)
67 {
68 return runInThread(s, thread, static_cast<QObject*>(nullptr), fun);
69 }
70};
71template <>
72class LIBDTKCORESHARED_EXPORT _TMP<void>
73{
74public:
75 inline static void runInThread(QSemaphore *s, QThread *thread, QObject *target, std::function<void()> fun)
76 {
77 FunctionCallProxy::proxyCall(s, thread, target, fun);
78 }
79
80 template <typename T>
81 inline static typename std::enable_if<!std::is_base_of<QObject, T>::value, void>::type
82 runInThread(QSemaphore *s, QThread *thread, T *, std::function<void()> fun)
83 {
84 return runInThread(s, thread, static_cast<QObject*>(nullptr), fun);
85 }
86};
87
88template <typename Fun, typename... Args>
89inline auto runInThread(QSemaphore *s, QThread *thread, QObject *target, Fun fun, Args&&... args) -> decltype(fun(args...))
90{
91 return _TMP<decltype(fun(args...))>::runInThread(s, thread, target, std::bind(fun, std::forward<Args>(args)...));
92}
93template <typename Fun, typename... Args>
94inline auto runInThread(QSemaphore *s, QThread *thread, Fun fun, Args&&... args) -> decltype(fun(args...))
95{
96 return runInThread(s, thread, nullptr, fun, std::forward<Args>(args)...);
97}
98template <typename Fun, typename... Args>
99inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
100 runInThread(QSemaphore *s, QThread *thread, QObject *target, typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
101{
102 return _TMP<typename QtPrivate::FunctionPointer<Fun>::ReturnType>::runInThread(s, thread, target, std::bind(fun, obj, std::forward<Args>(args)...));
103}
104template <typename Fun, typename... Args>
105inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
106 runInThread(QSemaphore *s, QThread *thread, typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
107{
108 return _TMP<typename QtPrivate::FunctionPointer<Fun>::ReturnType>::runInThread(s, thread, obj, std::bind(fun, obj, std::forward<Args>(args)...));
109}
110
111template <typename Fun, typename... Args>
112inline auto runInThread(QThread *thread, QObject *target, Fun fun, Args&&... args) -> decltype(fun(args...))
113{
114 QSemaphore s;
115
116 return runInThread(&s, thread, target, fun, std::forward<Args>(args)...);
117}
118template <typename Fun, typename... Args>
119inline auto runInThread(QThread *thread, Fun fun, Args&&... args) -> decltype(fun(args...))
120{
121 return runInThread(thread, nullptr, fun, std::forward<Args>(args)...);
122}
123template <typename T, typename Fun, typename... Args>
124inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
125 runInThread(QThread *thread, T *target, typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
126{
127 QSemaphore s;
128
129 return runInThread(&s, thread, target, obj, fun, std::forward<Args>(args)...);
130}
131
132template <typename Fun, typename... Args>
133inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
134 runInThread(QThread *thread, typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
135{
136 return runInThread(thread, obj, obj, fun, std::forward<Args>(args)...);
137}
138
139template <typename Fun, typename... Args>
140inline auto runInMainThread(QObject *target, Fun fun, Args&&... args) -> decltype(fun(args...))
141{
142 if (!QCoreApplication::instance()) {
143 return fun(std::forward<Args>(args)...);
144 }
145
146 return runInThread(QCoreApplication::instance()->thread(), target, fun, std::forward<Args>(args)...);
147}
148template <typename Fun, typename... Args>
149inline auto runInMainThread(Fun fun, Args&&... args) -> decltype(fun(args...))
150{
151 return runInMainThread(nullptr, fun, std::forward<Args>(args)...);
152}
153
154template <typename T, typename Fun, typename... Args>
155inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
156 runInMainThread(T *target, typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
157{
158 if (!QCoreApplication::instance()) {
159 return (obj->*fun)(std::forward<Args>(args)...);
160 }
161
162 return runInThread(QCoreApplication::instance()->thread(), target, obj, fun, std::forward<Args>(args)...);
163}
164template <typename Fun, typename... Args>
165inline typename QtPrivate::FunctionPointer<Fun>::ReturnType
166 runInMainThread(typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
167{
168 return runInMainThread(obj, obj, fun, std::forward<Args>(args)...);
169}
170}
171
172DCORE_END_NAMESPACE
173
174#endif // DTHREADUTILS_H
Definition: dthreadutils.h:38
Definition: dthreadutils.h:51