use crate::*;
use ctx::*;
use ptr::*;
use scheduler::*;
pub struct Fiber<T> {
handle: ThreadHandle<T>,
}
impl<T> Fiber<T> {
pub fn new<F: FnOnce() -> T + Clone + 'static>(closure: F) -> Self {
Self {
handle: RUNTIME.with(|rt| {
rt.get()
.spawn_not_schedule(|closure, _| closure(), (Box::new(closure), ()))
}),
}
}
pub fn new_capture<F: 'static, A: 'static + ApplyTo<F, Result = T> + Clone>(
closure: F,
args: A,
) -> Self {
Self {
handle: RUNTIME.with(|rt| rt.get().spawn_not_schedule(closure, args)),
}
}
fn get_thread(&self) -> Ptr<Context> {
self.handle.thread()
}
pub fn yield_(&self) {
crate::yield_thread();
}
pub fn start(&self) -> Result<(), &'static str> {
if self.get_thread().terminated {
return Err("Fiber terminated");
}
self.get_thread().scheduler.get().resume(self.get_thread());
Ok(())
}
pub fn join(self) -> Result<T, Box<dyn std::any::Any>>
where
T: 'static,
{
match self.handle.join() {
Ok(value) => Ok(value),
Err(e) => Err(e),
}
}
pub fn is_alive(&self) -> bool {
!self.handle.thread().terminated
}
pub fn suspend(&self) {
self.get_thread()
.scheduler
.get()
.suspend_thread(self.get_thread());
}
}