diff --git a/src/wine-host/utils.cpp b/src/wine-host/utils.cpp index 981bd3f2..172996c0 100644 --- a/src/wine-host/utils.cpp +++ b/src/wine-host/utils.cpp @@ -18,7 +18,8 @@ PluginContext::PluginContext() : context(), events_timer(context) {} -uint32_t WINAPI win32_thread_trampoline(std::function* entry_point) { +uint32_t WINAPI +win32_thread_trampoline(fu2::unique_function* entry_point) { (*entry_point)(); delete entry_point; diff --git a/src/wine-host/utils.h b/src/wine-host/utils.h index df8c263b..81f5c8e1 100644 --- a/src/wine-host/utils.h +++ b/src/wine-host/utils.h @@ -29,6 +29,7 @@ #include #include +#include /** * The delay between calls to the event loop at an even more than cinematic 30 @@ -122,19 +123,11 @@ class PluginContext { * We can't store the function pointer in the `Win32Thread` object because * moving a `Win32Thread` object would then cause issues. * - * @param win32_thread_trampoline A `std::function*` pointer to a - * function pointer, great. + * @param entry_point A `fu2::unique_function*` pointer to a function + * pointer, great. */ -uint32_t WINAPI win32_thread_trampoline(std::function* entry_point); - -/** - * Taken from the C++ reference: - * https://en.cppreference.com/w/cpp/thread/jthread - */ -template -std::decay_t decay_copy(T&& v) { - return std::forward(v); -} +uint32_t WINAPI +win32_thread_trampoline(fu2::unique_function* entry_point); /** * A simple RAII wrapper around the Win32 thread API that imitates @@ -166,24 +159,25 @@ class Win32Thread { * @param entry_point The thread entry point that should be run. * @param parameter The parameter passed to the entry point function. */ - template + template Win32Thread(Function&& f, Args&&... args) : handle( - CreateThread(nullptr, - 0, - reinterpret_cast( - win32_thread_trampoline), - // We'll capture the function by move since the - // lambda will often go out of scope in the time that - // the thread is starting. Alternatively we could - // wait for the thread to be up before continuing, - // that may be a bit safer. - new std::function([&, f = std::move(f)]() { - std::invoke( - f, decay_copy(std::forward(args))...); - }), - 0, - nullptr), + CreateThread( + nullptr, + 0, + reinterpret_cast( + win32_thread_trampoline), + // `std::function` does not support functions with move + // captures the function has to be copy-constructable. + // Function2's unique_function lets us capture and move our + // arguments to the lambda so we don't end up with dangling + // references. + new fu2::unique_function( + [f = std::move(f), ... args = std::move(args)]() mutable { + f(std::move(args)...); + }), + 0, + nullptr), CloseHandle) {} Win32Thread(const Win32Thread&) = delete;