diff options
Diffstat (limited to 'compat/run-in-thread.hpp')
| -rw-r--r-- | compat/run-in-thread.hpp | 112 |
1 files changed, 37 insertions, 75 deletions
diff --git a/compat/run-in-thread.hpp b/compat/run-in-thread.hpp index ba99d0b9..c552c600 100644 --- a/compat/run-in-thread.hpp +++ b/compat/run-in-thread.hpp @@ -1,8 +1,12 @@ #pragma once -#include "ndebug-guard.hpp" +/* Copyright (c) 2016 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ -#include <cassert> #include <thread> #include <condition_variable> #include <utility> @@ -10,98 +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 run_in_thread_sync(QObject* obj, F&& fun) - -> typename qt_impl_detail::run_in_thread_traits<decltype(std::forward<F>(fun)())>::ret_type +void run_in_thread_sync(QObject* obj, F&& fun) { - using lock_guard = std::unique_lock<std::mutex>; - - using traits = qt_impl_detail::run_in_thread_traits<decltype(std::forward<F>(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); - } + if (obj->thread() == QThread::currentThread()) + return (void)fun(); - 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); } |
