// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QQMLTHREAD_P_H #define QQMLTHREAD_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include QT_BEGIN_NAMESPACE class QThread; class QMutex; class QQmlThreadPrivate; class QQmlThread { public: QQmlThread(); virtual ~QQmlThread(); void startup(); void shutdown(); bool isShutdown() const; QMutex &mutex(); void lock(); void unlock(); void wakeOne(); void wait(); QThread *thread() const; bool isThisThread() const; // Synchronously invoke a method in the thread template void callMethodInThread(Method &&method, Args &&...args); // Synchronously invoke a method in the main thread. If the main thread is // blocked in a callMethodInThread() call, the call is made from within that // call. template void callMethodInMain(Method &&method, Args &&...args); // Asynchronously invoke a method in the thread. template void postMethodToThread(Method &&method, Args &&...args); // Asynchronously invoke a method in the main thread. template void postMethodToMain(Method &&method, Args &&...args); void waitForNextMessage(); void discardMessages(); private: friend class QQmlThreadPrivate; struct Message { Message() : next(nullptr) {} virtual ~Message() {} Message *next; virtual void call(QQmlThread *) = 0; }; template Message *createMessageFromMethod(Method &&method, Args &&...args); void internalCallMethodInThread(Message *); void internalCallMethodInMain(Message *); void internalPostMethodToThread(Message *); void internalPostMethodToMain(Message *); QQmlThreadPrivate *d; }; namespace QtPrivate { template struct member_function_traits; template struct member_function_traits { using class_type = Object; }; } template QQmlThread::Message *QQmlThread::createMessageFromMethod(Method &&method, Args &&...args) { struct I : public Message { Method m; std::tuple...> arguments; I(Method &&method, Args&& ...args) : m(std::forward(method)), arguments(std::forward(args)...) {} void call(QQmlThread *thread) override { using class_type = typename QtPrivate::member_function_traits::class_type; class_type *me = static_cast(thread); std::apply(m, std::tuple_cat(std::make_tuple(me), arguments)); } }; return new I(std::forward(method), std::forward(args)...); } template void QQmlThread::callMethodInMain(Method &&method, Args&& ...args) { Message *m = createMessageFromMethod(std::forward(method), std::forward(args)...); internalCallMethodInMain(m); } template void QQmlThread::callMethodInThread(Method &&method, Args&& ...args) { Message *m = createMessageFromMethod(std::forward(method), std::forward(args)...); internalCallMethodInThread(m); } template void QQmlThread::postMethodToThread(Method &&method, Args&& ...args) { Message *m = createMessageFromMethod(std::forward(method), std::forward(args)...); internalPostMethodToThread(m); } template void QQmlThread::postMethodToMain(Method &&method, Args&& ...args) { Message *m = createMessageFromMethod(std::forward(method), std::forward(args)...); internalPostMethodToMain(m); } QT_END_NAMESPACE #endif // QQMLTHREAD_P_H