From 644494f7cf27cb8dbe89a50885f57a7266a06e63 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 26 Oct 2016 07:25:50 +0200 Subject: compat/util: split out run-in-thread{,-async} --- compat/run-in-thread.hpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++ compat/util.hpp | 87 +----------------------------------------------- 2 files changed, 86 insertions(+), 86 deletions(-) create mode 100644 compat/run-in-thread.hpp diff --git a/compat/run-in-thread.hpp b/compat/run-in-thread.hpp new file mode 100644 index 00000000..d377f625 --- /dev/null +++ b/compat/run-in-thread.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include + +#include +#include +#include + +namespace detail { + +template +struct run_in_thread_traits +{ + using type = t; + using ret_type = t&&; + static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; } + static inline ret_type&& pass(ret_type&& val) { return std::move(val); } + template static ret_type call(F& fun) { return std::move(fun()); } +}; + +template<> +struct run_in_thread_traits +{ + using type = unsigned char; + using ret_type = void; + static inline void assign(unsigned char&, unsigned char&&) {} + static inline void pass(type&&) {} + template static type&& call(F& fun) { fun(); return std::move(type(0)); } +}; + +} + +template +auto run_in_thread_sync(QObject* obj, F&& fun) + -> typename detail::run_in_thread_traits(fun)())>::ret_type +{ + using lock_guard = std::unique_lock; + + std::mutex mtx; + lock_guard guard(mtx); + std::condition_variable cvar; + + std::thread::id waiting_thread = std::this_thread::get_id(); + + using traits = detail::run_in_thread_traits(fun)())>; + + typename traits::type ret; + + bool skip_wait = false; + + { + QObject src; + src.moveToThread(obj->thread()); + QObject::connect(&src, + &QObject::destroyed, + obj, + [&]() { + std::thread::id calling_thread = std::this_thread::get_id(); + if (waiting_thread == calling_thread) + { + skip_wait = true; + traits::assign(ret, traits::call(fun)); + } + else + { + lock_guard guard(mtx); + traits::assign(ret, traits::call(fun)); + cvar.notify_one(); + } + }, + Qt::AutoConnection); + } + + if (!skip_wait) + cvar.wait(guard); + return traits::pass(std::move(ret)); +} + +template +void run_in_thread_async(QObject* obj, F&& fun) +{ + QObject src; + src.moveToThread(obj->thread()); + QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection); +} diff --git a/compat/util.hpp b/compat/util.hpp index 528ae1a8..7a6858a3 100644 --- a/compat/util.hpp +++ b/compat/util.hpp @@ -1,16 +1,10 @@ #pragma once #include "make-unique.hpp" +#include "run-in-thread.hpp" #include #include -#include -#include -#include -#include - -#include -#include #define progn(...) ([&]() { __VA_ARGS__ }()) template using mem = std::shared_ptr; @@ -47,82 +41,3 @@ inline auto clamp(const t& val, const u& min, const w& max) -> decltype(val * mi { return ::detail::clamp_(val, min, max); } - -namespace detail { - -template -struct run_in_thread_traits -{ - using type = t; - using ret_type = t&&; - static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; } - static inline ret_type&& pass(ret_type&& val) { return std::move(val); } - template static ret_type call(F& fun) { return std::move(fun()); } -}; - -template<> -struct run_in_thread_traits -{ - using type = unsigned char; - using ret_type = void; - static inline void assign(unsigned char&, unsigned char&&) {} - static inline void pass(type&&) {} - template static type&& call(F& fun) { fun(); return std::move(type(0)); } -}; - -} - -template -auto run_in_thread_sync(QObject* obj, F&& fun) - -> typename detail::run_in_thread_traits(fun)())>::ret_type -{ - using lock_guard = std::unique_lock; - - std::mutex mtx; - lock_guard guard(mtx); - std::condition_variable cvar; - - std::thread::id waiting_thread = std::this_thread::get_id(); - - using traits = detail::run_in_thread_traits(fun)())>; - - typename traits::type ret; - - bool skip_wait = false; - - { - QObject src; - src.moveToThread(obj->thread()); - QObject::connect(&src, - &QObject::destroyed, - obj, - [&]() { - std::thread::id calling_thread = std::this_thread::get_id(); - if (waiting_thread == calling_thread) - { - skip_wait = true; - traits::assign(ret, traits::call(fun)); - } - else - { - lock_guard guard(mtx); - traits::assign(ret, traits::call(fun)); - cvar.notify_one(); - } - }, - Qt::AutoConnection); - } - - if (!skip_wait) - cvar.wait(guard); - return traits::pass(std::move(ret)); -} - -template -void run_in_thread_async(QObject* obj, F&& fun) -{ - QObject src; - src.moveToThread(obj->thread()); - QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection); -} - -- cgit v1.2.3