diff options
Diffstat (limited to 'compat/run-in-thread.hpp')
-rw-r--r-- | compat/run-in-thread.hpp | 108 |
1 files changed, 31 insertions, 77 deletions
diff --git a/compat/run-in-thread.hpp b/compat/run-in-thread.hpp index b425532e..c552c600 100644 --- a/compat/run-in-thread.hpp +++ b/compat/run-in-thread.hpp @@ -7,9 +7,6 @@ * copyright notice and this permission notice appear in all copies. */ -#include "macros.hpp" - -#include <cassert> #include <thread> #include <condition_variable> #include <utility> @@ -17,99 +14,56 @@ #include <QObject> #include <QThread> -namespace qt_impl_detail { - -template<typename t> -struct run_in_thread_traits +namespace impl_run_in_thread { +struct semaphore final { - using type = t; - using ret_type = t; - static inline void assign(t& lvalue, const t& rvalue) { lvalue = rvalue; } - static inline t pass(const t& val) { return val; } - template<typename F> static inline t call(F&& fun) { return std::move(fun()); } -}; + using lock_guard = std::unique_lock<std::mutex>; + std::mutex mtx; + std::condition_variable cvar; + bool flag = false; -template<typename u> -struct run_in_thread_traits<u&&> -{ - using t = typename std::remove_reference<u>::type; - using type = t; - using ret_type = u; - static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; } - static inline t&& pass(t&& val) { return val; } - template<typename F> static inline t&& call(F&& fun) { return std::move(fun()); } -}; + semaphore() = default; -template<> -struct run_in_thread_traits<void> -{ - using type = unsigned char; - using ret_type = void; - static inline void assign(unsigned char&, unsigned char&&) {} - static inline void pass(type&&) {} - template<typename F> static type call(F&& fun) { fun(); return type(0); } -}; + void wait() + { + lock_guard guard(mtx); + while (!flag) + cvar.wait(guard); + } + void notify() + { + lock_guard guard(mtx); + flag = true; + cvar.notify_one(); + } +}; } template<typename F> -auto never_inline -run_in_thread_sync(QObject* obj, F&& fun) - -> typename qt_impl_detail::run_in_thread_traits<decltype(fun())>::ret_type +void run_in_thread_sync(QObject* obj, F&& fun) { - using lock_guard = std::unique_lock<std::mutex>; + if (obj->thread() == QThread::currentThread()) + return (void)fun(); - using traits = qt_impl_detail::run_in_thread_traits<decltype(fun())>; - - typename traits::type ret; - - struct semaphore final - { - std::mutex mtx; - std::condition_variable cvar; - bool flag; - - semaphore() : flag(false) {} - - void wait() - { - lock_guard guard(mtx); - while (!flag) - cvar.wait(guard); - } - - void notify() - { - lock_guard guard(mtx); - flag = true; - cvar.notify_one(); - } - }; - - semaphore sem; + impl_run_in_thread::semaphore sem; { QObject src; - QObject::connect(&src, - &QObject::destroyed, - obj, - [&]() { - traits::assign(ret, traits::call(fun)); - sem.notify(); - }, - Qt::AutoConnection); + QObject::connect(&src, &QObject::destroyed, + obj, [&] { fun(); sem.notify(); }, + Qt::QueuedConnection); } sem.wait(); - return traits::pass(std::move(ret)); } template<typename F> void run_in_thread_async(QObject* obj, F&& fun) { + if (obj->thread() == QThread::currentThread()) + return (void)fun(); + QObject src; - QThread* t(obj->thread()); - assert(t); - src.moveToThread(t); - QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection); + QObject::connect(&src, &QObject::destroyed, obj, std::forward<F>(fun), Qt::QueuedConnection); } |