use crate::coroutine_impl::{current_cancel_data, is_coroutine};
use crate::coroutine_impl::{CoroutineImpl, EventResult, EventSource, EventSubscriber};
use crate::likely::{likely, unlikely};
use crate::scheduler::get_scheduler;
use generator::{co_get_yield, co_set_para, co_yield_with};
struct Yield {}
impl EventSource for Yield {
fn subscribe(&mut self, co: CoroutineImpl) {
get_scheduler().schedule(co);
}
}
#[inline]
pub fn yield_with<T: EventSource>(resource: &T) {
let cancel = current_cancel_data();
if unlikely(cancel.is_canceled()) {
co_set_para(std::io::Error::other("Canceled"));
return resource.yield_back(cancel);
}
let r = unsafe {
std::mem::transmute::<*const (dyn EventSource + '_), *mut (dyn EventSource + 'static)>(
resource as &dyn EventSource,
)
};
let es = EventSubscriber::new(r);
co_yield_with(es);
resource.yield_back(cancel);
cancel.clear();
}
#[inline]
pub fn yield_with_io<T: EventSource>(resource: &T, is_coroutine: bool) {
if likely(is_coroutine) {
#[cfg(feature = "io_cancel")]
yield_with(resource);
#[cfg(not(feature = "io_cancel"))]
{
let r = unsafe {
std::mem::transmute::<*const (dyn EventSource + '_), *mut (dyn EventSource + 'static)>(
resource as &dyn EventSource,
)
};
let es = EventSubscriber::new(r);
co_yield_with(es);
}
} else {
let r = unsafe {
std::mem::transmute::<*const (dyn EventSource + '_), *mut (dyn EventSource + 'static)>(
resource as &dyn EventSource,
)
};
let es = EventSubscriber::new(r);
crate::io::thread::PROXY_CO_SENDER.with(|tx| {
tx.send(es).unwrap();
});
std::thread::park();
}
}
#[cold]
#[inline]
pub fn set_co_para(co: &mut CoroutineImpl, v: EventResult) {
co.set_para(v);
}
#[inline]
pub fn get_co_para() -> Option<EventResult> {
co_get_yield::<EventResult>()
}
#[inline]
pub fn yield_now() {
if unlikely(!is_coroutine()) {
return std::thread::yield_now();
}
let y = Yield {};
yield_with(&y);
}