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:
parent
1e77a92285
commit
1f2029ecbe
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/util.rs
22
src/util.rs
|
@ -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::*;
|
||||||
|
|
Loading…
Reference in a new issue