mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
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:
+15
-15
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user