pub mod prelude;
mod exec;
mod soft;
pub use self::{
exec::{ExecOutput, ThrExec},
soft::{pending_size, SoftThrToken, SoftThread, PRIORITY_LEVELS},
};
#[doc(inline)]
pub use drone_core_macros::thr_pool as pool;
#[doc(inline)]
pub use drone_core_macros::thr_soft as soft;
use crate::{
fib::{Chain, RootFiber},
token::Token,
};
use core::sync::atomic::{AtomicU16, Ordering};
pub unsafe trait Thread: Sized + Sync + 'static {
type Local: Sized + 'static;
const COUNT: u16;
fn pool() -> *const Self;
fn current() -> *const AtomicU16;
fn fib_chain(&self) -> &Chain;
fn local_opaque(&self) -> &LocalOpaque<Self>;
#[inline]
fn local() -> &'static Self::Local {
Self::local_checked().expect("getting thread-local outside of thread pool")
}
#[inline]
fn local_checked() -> Option<&'static Self::Local> {
unsafe {
let current = (*Self::current()).load(Ordering::Relaxed);
if current == 0 {
None
} else {
Some((*Self::pool().add(usize::from(current) - 1)).local_opaque().reveal())
}
}
}
#[inline]
unsafe fn resume(&self) {
unsafe { self.fib_chain().drain().for_each(drop) };
}
#[inline]
unsafe fn call(thr_idx: u16, f: unsafe fn(&'static Self)) {
unsafe {
let preempted = (*Self::current()).load(Ordering::Relaxed);
(*Self::current()).store(thr_idx + 1, Ordering::Relaxed);
f(&*Self::pool().add(usize::from(thr_idx)));
(*Self::current()).store(preempted, Ordering::Relaxed);
}
}
}
pub unsafe trait ThrToken
where
Self: Sized + Clone + Copy,
Self: Send + Sync + 'static,
Self: Token,
{
type Thread: Thread;
const THR_IDX: u16;
#[inline]
fn to_thr(self) -> &'static Self::Thread {
unsafe { &*Self::Thread::pool().add(usize::from(Self::THR_IDX)) }
}
#[inline]
fn add_fib<F>(self, fib: F)
where
F: RootFiber + Send,
{
self.to_thr().fib_chain().add(fib);
}
#[inline]
fn add_fib_factory<C, F>(self, factory: C)
where
C: FnOnce() -> F + Send + 'static,
F: RootFiber,
{
self.to_thr().fib_chain().add(factory());
}
#[inline]
fn is_empty(self) -> bool {
self.to_thr().fib_chain().is_empty()
}
}
#[repr(transparent)]
pub struct LocalOpaque<T: Thread>(T::Local);
unsafe impl<T: Thread> ::core::marker::Sync for LocalOpaque<T> {}
impl<T: Thread> LocalOpaque<T> {
#[inline]
pub const fn new(local: T::Local) -> Self {
Self(local)
}
unsafe fn reveal(&self) -> &T::Local {
&self.0
}
}