use crate::event::{SchedImpl, Scheduler};
use crate::thread::{self, JoinHandle, Semaphore};
use crate::Result;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use hipool::{Allocator, Boxed, Pool};
pub trait Runnable {
type Context;
fn active(&mut self, ctx: &mut Self::Context) -> Result<()>;
}
impl<'a, T: Runnable<Context = ThreadContext<'a, A>> + Send, A: Allocator> Runnable
for Boxed<'a, T, A>
{
type Context = T::Context;
fn active(&mut self, ctx: &mut Self::Context) -> Result<()> {
Runnable::active(&mut **self, ctx)
}
}
#[repr(C)]
pub struct ThreadContext<'a, A: Allocator> {
sched: Boxed<'a, Scheduler, A>,
}
impl<'a, A: Allocator> ThreadContext<'a, A> {
pub fn sched(&mut self) -> &mut Scheduler {
self.sched.as_mut()
}
pub fn stop(&mut self) {
self.sched.stop();
}
}
#[repr(C)]
pub(crate) struct Thread<'a, T, A: Allocator> {
ctx: ThreadContext<'a, A>,
body: T,
}
unsafe impl<T: Send, A: Allocator + Pool> Send for Thread<'_, T, A> {}
impl<T: Runnable<Context = ThreadContext<'static, A>> + Send + 'static, A: Allocator + Pool>
Thread<'static, T, A>
{
pub(crate) fn new_in(pool: &'static A, body: T) -> Result<ThreadProxy> {
let sched = SchedImpl::new_in(pool)?;
let mut this = Boxed::new_in(
pool,
Self {
ctx: ThreadContext { sched },
body,
},
)?;
let sem = Semaphore::new().unwrap();
let sem_ref = unsafe { &*(&sem as *const Semaphore) };
let handle = thread::spawn(move || match this.active() {
Ok(_) => {
sem_ref.post();
this.ctx.sched.run();
}
Err(err) => panic!("Thread Body active failed, errno = {err}"),
});
sem_ref.wait();
Ok(ThreadProxy {
handle: ManuallyDrop::new(handle),
mark: PhantomData,
})
}
}
impl<'a, T: Runnable<Context = ThreadContext<'a, A>> + Send, A: Allocator> Thread<'a, T, A> {
fn active(&mut self) -> Result<()> {
self.body.active(&mut self.ctx)
}
}
pub struct ThreadProxy {
handle: ManuallyDrop<JoinHandle<()>>,
mark: PhantomData<*const ()>,
}
unsafe impl Send for ThreadProxy {}
impl ThreadProxy {
pub(crate) fn join(&mut self) {
let _ = unsafe { ManuallyDrop::take(&mut self.handle) }.join();
}
}