mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +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"
|
#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
|
uint32_t WINAPI
|
||||||
win32_thread_trampoline(fu2::unique_function<void()>* entry_point) {
|
win32_thread_trampoline(fu2::unique_function<void()>* entry_point) {
|
||||||
(*entry_point)();
|
(*entry_point)();
|
||||||
@@ -85,3 +70,18 @@ Win32Timer& Win32Timer::operator=(Win32Timer&& o) {
|
|||||||
|
|
||||||
return *this;
|
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"
|
#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
|
* 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
|
* 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::steady_clock::duration timer_interval =
|
||||||
std::chrono::milliseconds(1000) / 60;
|
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