1
0
Fork 0

Replace spawn_unchecked with static lifetimes

These things don't need to hold references, so this gets rid of some
nasty c ode.
This commit is contained in:
Robbert van der Helm 2022-02-05 16:09:59 +01:00
parent 1e77a92285
commit 1f2029ecbe
3 changed files with 10 additions and 37 deletions

View file

@ -90,14 +90,15 @@ pub trait GuiContext {
/// thread. /// thread.
/// ///
/// This is never used generically, but having this as a trait will cause any missing functions on /// This is never used generically, but having this as a trait will cause any missing functions on
/// an implementation to show up as compiler errors even when using a different platform. /// an implementation to show up as compiler errors even when using a different platform. And since
/// the tasks and executor will be sent to a thread, they need to have static lifetimes.
/// ///
/// TODO: At some point rethink the design to make it possible to have a singleton message queue for /// TODO: At some point rethink the design to make it possible to have a singleton message queue for
/// all instances of a plugin. /// all instances of a plugin.
pub(crate) trait EventLoop<T, E> pub(crate) trait EventLoop<T, E>
where where
T: Send, T: Send + 'static,
E: MainThreadExecutor<T>, E: MainThreadExecutor<T> + 'static,
{ {
/// Create and start a new event loop. The thread this is called on will be designated as the /// Create and start a new event loop. The thread this is called on will be designated as the
/// main thread, so this should be called when constructing the wrapper. /// main thread, so this should be called when constructing the wrapper.

View file

@ -24,7 +24,6 @@ use std::thread::{self, JoinHandle, ThreadId};
use super::{EventLoop, MainThreadExecutor}; use super::{EventLoop, MainThreadExecutor};
use crate::nih_log; use crate::nih_log;
use crate::util::ThreadSpawnUnchecked;
/// See [super::EventLoop]. /// See [super::EventLoop].
pub(crate) struct LinuxEventLoop<T, E> { pub(crate) struct LinuxEventLoop<T, E> {
@ -56,8 +55,8 @@ enum Message<T> {
impl<T, E> EventLoop<T, E> for LinuxEventLoop<T, E> impl<T, E> EventLoop<T, E> for LinuxEventLoop<T, E>
where where
T: Send, T: Send + 'static,
E: MainThreadExecutor<T>, E: MainThreadExecutor<T> + 'static,
{ {
fn new_and_spawn(executor: Weak<E>) -> Self { fn new_and_spawn(executor: Weak<E>) -> Self {
let (sender, receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY); let (sender, receiver) = channel::bounded(super::TASK_QUEUE_CAPACITY);
@ -66,17 +65,12 @@ where
executor: executor.clone(), executor: executor.clone(),
main_thread_id: thread::current().id(), main_thread_id: thread::current().id(),
// With our drop implementation we guarentee that this thread never outlives this struct // With our drop implementation we guarentee that this thread never outlives this struct
worker_thread: Some(unsafe { worker_thread: Some(
thread::Builder::new() thread::Builder::new()
.name(String::from("worker")) .name(String::from("worker"))
// The worker thread gets joined when this struct gets dropped, and if this .spawn(move || worker_thread(receiver, executor))
// struct never gets dropped it just sits there idly. Panics cannot be unwound, .expect("Could not spawn worker thread"),
// but in plugin-land we have bigger worries than that. ),
// This is the same as the `.spawn_unchecked()` function, but without requiring
// a nightly compiler.
.spawn_unchecked_2(move || worker_thread(receiver, executor))
.expect("Could not spawn worker thread")
}),
worker_thread_channel: sender, worker_thread_channel: sender,
} }
} }

View file

@ -41,28 +41,6 @@ pub fn midi_note_to_freq(pitch: u8) -> f32 {
2.0f32.powf((pitch as f32 - 69.0) / 12.0) * 440.0 2.0f32.powf((pitch as f32 - 69.0) / 12.0) * 440.0
} }
/// A version of [std::thread::Builder::spawn_unchecked()] that works on the stable compiler.
/// Implementation courtesy of Yandros on the Rust Discord.
pub(crate) trait ThreadSpawnUnchecked {
unsafe fn spawn_unchecked_2<F, R>(self, f: F) -> std::io::Result<std::thread::JoinHandle<R>>
where
F: FnOnce() -> R + Send,
R: 'static + Send;
}
impl ThreadSpawnUnchecked for std::thread::Builder {
unsafe fn spawn_unchecked_2<F, R>(self, f: F) -> std::io::Result<std::thread::JoinHandle<R>>
where
F: FnOnce() -> R + Send,
R: 'static + Send,
{
let f: Box<dyn '_ + FnOnce() -> R + Send> = Box::new(f);
// SAFETY: same-layout since only a lifetime difference
let f: Box<dyn 'static + FnOnce() -> R + Send> = std::mem::transmute(f);
self.spawn(f)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;