Properly forward arguments in Win32Thread

This commit is contained in:
Robbert van der Helm
2020-10-27 18:28:23 +01:00
parent a6b5951d81
commit bafc36614b
2 changed files with 28 additions and 27 deletions
-8
View File
@@ -25,14 +25,6 @@ uint32_t WINAPI win32_thread_trampoline(std::function<void()>* entry_point) {
return 0; return 0;
} }
Win32Thread::~Win32Thread() {
// Imitate std::jthread's joining behaviour, the thread handle will be
// cleaned up by the `std::unique_ptr`
if (handle) {
WaitForSingleObject(handle.get(), INFINITE);
}
}
Win32Thread::Win32Thread(Win32Thread&& o) : handle(std::move(o.handle)) {} Win32Thread::Win32Thread(Win32Thread&& o) : handle(std::move(o.handle)) {}
Win32Thread& Win32Thread::operator=(Win32Thread&& o) { Win32Thread& Win32Thread::operator=(Win32Thread&& o) {
+28 -19
View File
@@ -127,9 +127,18 @@ class PluginContext {
*/ */
uint32_t WINAPI win32_thread_trampoline(std::function<void()>* entry_point); uint32_t WINAPI win32_thread_trampoline(std::function<void()>* entry_point);
/**
* Taken from the C++ reference:
* https://en.cppreference.com/w/cpp/thread/jthread
*/
template <class T>
std::decay_t<T> decay_copy(T&& v) {
return std::forward<T>(v);
}
/** /**
* A simple RAII wrapper around the Win32 thread API that imitates * A simple RAII wrapper around the Win32 thread API that imitates
* `std::jthread`. * `std::thread`.
* *
* `std::thread` directly uses pthreads. This means that, like with * `std::thread` directly uses pthreads. This means that, like with
* `CreateThread()`, some thread local information does not get initialized * `CreateThread()`, some thread local information does not get initialized
@@ -152,30 +161,30 @@ class Win32Thread {
/** /**
* Constructor that immediately starts running the thread. This works * Constructor that immediately starts running the thread. This works
* equivalently to `std::jthread`. * equivalently to `std::thread`.
* *
* @param entry_point The thread entry point that should be run. * @param entry_point The thread entry point that should be run.
* @param parameter The parameter passed to the entry point function. * @param parameter The parameter passed to the entry point function.
*/ */
template <class Function, class... Args> template <class Function, class... Args>
Win32Thread(Function&& f, Args&&... args) Win32Thread(Function&& f, Args&&... args)
: handle(CreateThread( : handle(
nullptr, CreateThread(nullptr,
0, 0,
reinterpret_cast<LPTHREAD_START_ROUTINE>( reinterpret_cast<LPTHREAD_START_ROUTINE>(
win32_thread_trampoline), win32_thread_trampoline),
new std::function<void()>( // We'll capture the function by move since the
[f = std::move(f), ... args = std::move(args)]() { // lambda will often go out of scope in the time that
std::invoke(f, args...); // the thread is starting. Alternatively we could
}), // wait for the thread to be up before continuing,
0, // that may be a bit safer.
nullptr), new std::function<void()>([&, f = std::move(f)]() {
CloseHandle) {} std::invoke(
f, decay_copy(std::forward<Args>(args))...);
/** }),
* Join the thread on destruction, just like `std::jthread` does. 0,
*/ nullptr),
~Win32Thread(); CloseHandle) {}
Win32Thread(const Win32Thread&) = delete; Win32Thread(const Win32Thread&) = delete;
Win32Thread& operator=(const Win32Thread&) = delete; Win32Thread& operator=(const Win32Thread&) = delete;