Rearrange src/wine-host/utils.h

We're going to need to spawn a Win32Thread in the MainContext to act as
a watchdog.
This commit is contained in:
Robbert van der Helm
2021-05-01 15:15:52 +02:00
parent b22f207aee
commit aeca37d795
2 changed files with 131 additions and 131 deletions
+15 -15
View File
@@ -16,21 +16,6 @@
#include "utils.h"
MainContext::MainContext() : context(), events_timer(context) {}
void MainContext::run() {
context.run();
}
void MainContext::stop() {
context.stop();
}
void MainContext::update_timer_interval(
std::chrono::steady_clock::duration new_interval) {
timer_interval = new_interval;
}
uint32_t WINAPI
win32_thread_trampoline(fu2::unique_function<void()>* entry_point) {
(*entry_point)();
@@ -85,3 +70,18 @@ Win32Timer& Win32Timer::operator=(Win32Timer&& o) {
return *this;
}
MainContext::MainContext() : context(), events_timer(context) {}
void MainContext::run() {
context.run();
}
void MainContext::stop() {
context.stop();
}
void MainContext::update_timer_interval(
std::chrono::steady_clock::duration new_interval) {
timer_interval = new_interval;
}
+116 -116
View File
@@ -34,6 +34,122 @@
#include "../common/utils.h"
/**
* A proxy function that calls `Win32Thread::entry_point` since `CreateThread()`
* is not usable with lambdas directly. Calling the passed function will invoke
* the lambda with the arguments passed during `Win32Thread`'s constructor. This
* function deallocates the function after it's finished executing.
*
* We can't store the function pointer in the `Win32Thread` object because
* moving a `Win32Thread` object would then cause issues.
*
* @param entry_point A `fu2::unique_function<void()>*` pointer to a function
* pointer, great.
*/
uint32_t WINAPI
win32_thread_trampoline(fu2::unique_function<void()>* entry_point);
/**
* A simple RAII wrapper around the Win32 thread API that imitates
* `std::jthread`, including implicit joining (or waiting, since this is Win32)
* on destruction.
*
* `std::thread` uses pthreads directly in Winelib (since this is technically a
* regular Linux application). This means that when using
* `std::thread`/`std::jthread` directly, some thread local information that
* `CreateThread()` would normally set does not get initialized. This could then
* lead to memory errors. This wrapper aims to be equivalent to `std::jthread`,
* but using the Win32 API instead.
*
* @note This should be used instead of `std::thread` or `std::jthread` whenever
* the thread directly calls third party library code, i.e. `LoadLibrary()`,
* `FreeLibrary()`, the plugin's entry point, or any of the `AEffect::*()`
* functions.
*/
class Win32Thread {
public:
/**
* Constructor that does not start any thread yet.
*/
Win32Thread();
/**
* Constructor that immediately starts running the thread. This works
* equivalently to `std::jthread`.
*
* @param entry_point The thread entry point that should be run.
* @param parameter The parameter passed to the entry point function.
*/
template <typename Function, typename... Args>
Win32Thread(Function&& f, Args&&... args)
: handle(
CreateThread(
nullptr,
0,
reinterpret_cast<LPTHREAD_START_ROUTINE>(
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<void()>(
[f = std::move(f), ... args = std::move(args)]() mutable {
f(std::move(args)...);
}),
0,
nullptr),
CloseHandle) {}
/**
* Join (or wait on, since this is WIn32) the thread on shutdown, just like
* `std::jthread` does.
*/
~Win32Thread();
Win32Thread(const Win32Thread&) = delete;
Win32Thread& operator=(const Win32Thread&) = delete;
Win32Thread(Win32Thread&&);
Win32Thread& operator=(Win32Thread&&);
private:
// FIXME: This emits `-Wignored-attributes` as of Wine 5.22
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes"
/**
* The handle for the thread that is running, will be a null pointer if this
* class was constructed with the default constructor.
*/
std::unique_ptr<std::remove_pointer_t<HANDLE>, decltype(&CloseHandle)>
handle;
#pragma GCC diagnostic pop
};
/**
* A simple RAII wrapper around `SetTimer`. Does not support timer procs since
* we don't use them.
*/
class Win32Timer {
public:
Win32Timer();
Win32Timer(HWND window_handle, size_t timer_id, unsigned int interval_ms);
~Win32Timer();
Win32Timer(const Win32Timer&) = delete;
Win32Timer& operator=(const Win32Timer&) = delete;
Win32Timer(Win32Timer&&);
Win32Timer& operator=(Win32Timer&&);
private:
HWND window_handle;
std::optional<size_t> timer_id;
};
/**
* A wrapper around `boost::asio::io_context()` to serve as the application's
* main IO context. A single instance is shared for all plugins in a plugin
@@ -161,119 +277,3 @@ class MainContext {
std::chrono::steady_clock::duration timer_interval =
std::chrono::milliseconds(1000) / 60;
};
/**
* A proxy function that calls `Win32Thread::entry_point` since `CreateThread()`
* is not usable with lambdas directly. Calling the passed function will invoke
* the lambda with the arguments passed during `Win32Thread`'s constructor. This
* function deallocates the function after it's finished executing.
*
* We can't store the function pointer in the `Win32Thread` object because
* moving a `Win32Thread` object would then cause issues.
*
* @param entry_point A `fu2::unique_function<void()>*` pointer to a function
* pointer, great.
*/
uint32_t WINAPI
win32_thread_trampoline(fu2::unique_function<void()>* entry_point);
/**
* A simple RAII wrapper around the Win32 thread API that imitates
* `std::jthread`, including implicit joining (or waiting, since this is Win32)
* on destruction.
*
* `std::thread` uses pthreads directly in Winelib (since this is technically a
* regular Linux application). This means that when using
* `std::thread`/`std::jthread` directly, some thread local information that
* `CreateThread()` would normally set does not get initialized. This could then
* lead to memory errors. This wrapper aims to be equivalent to `std::jthread`,
* but using the Win32 API instead.
*
* @note This should be used instead of `std::thread` or `std::jthread` whenever
* the thread directly calls third party library code, i.e. `LoadLibrary()`,
* `FreeLibrary()`, the plugin's entry point, or any of the `AEffect::*()`
* functions.
*/
class Win32Thread {
public:
/**
* Constructor that does not start any thread yet.
*/
Win32Thread();
/**
* Constructor that immediately starts running the thread. This works
* equivalently to `std::jthread`.
*
* @param entry_point The thread entry point that should be run.
* @param parameter The parameter passed to the entry point function.
*/
template <typename Function, typename... Args>
Win32Thread(Function&& f, Args&&... args)
: handle(
CreateThread(
nullptr,
0,
reinterpret_cast<LPTHREAD_START_ROUTINE>(
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<void()>(
[f = std::move(f), ... args = std::move(args)]() mutable {
f(std::move(args)...);
}),
0,
nullptr),
CloseHandle) {}
/**
* Join (or wait on, since this is WIn32) the thread on shutdown, just like
* `std::jthread` does.
*/
~Win32Thread();
Win32Thread(const Win32Thread&) = delete;
Win32Thread& operator=(const Win32Thread&) = delete;
Win32Thread(Win32Thread&&);
Win32Thread& operator=(Win32Thread&&);
private:
// FIXME: This emits `-Wignored-attributes` as of Wine 5.22
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes"
/**
* The handle for the thread that is running, will be a null pointer if this
* class was constructed with the default constructor.
*/
std::unique_ptr<std::remove_pointer_t<HANDLE>, decltype(&CloseHandle)>
handle;
#pragma GCC diagnostic pop
};
/**
* A simple RAII wrapper around `SetTimer`. Does not support timer procs since
* we don't use them.
*/
class Win32Timer {
public:
Win32Timer();
Win32Timer(HWND window_handle, size_t timer_id, unsigned int interval_ms);
~Win32Timer();
Win32Timer(const Win32Timer&) = delete;
Win32Timer& operator=(const Win32Timer&) = delete;
Win32Timer(Win32Timer&&);
Win32Timer& operator=(Win32Timer&&);
private:
HWND window_handle;
std::optional<size_t> timer_id;
};