#[cfg(feature = "executor-interrupt")]
compile_error!("`executor-interrupt` is not supported with `arch-std`.");
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
use std::marker::PhantomData;
use std::sync::{Condvar, Mutex};
pub use embassy_executor_macros::main_std as main;
use crate::{raw, Spawner};
#[export_name = "__pender"]
fn __pender(context: *mut ()) {
let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
signaler.signal()
}
pub struct Executor {
inner: raw::Executor,
not_send: PhantomData<*mut ()>,
signaler: &'static Signaler,
}
impl Executor {
pub fn new() -> Self {
let signaler = Box::leak(Box::new(Signaler::new()));
Self {
inner: raw::Executor::new(signaler as *mut Signaler as *mut ()),
not_send: PhantomData,
signaler,
}
}
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
init(self.inner.spawner());
loop {
unsafe { self.inner.poll() };
self.signaler.wait()
}
}
}
struct Signaler {
mutex: Mutex<bool>,
condvar: Condvar,
}
impl Signaler {
fn new() -> Self {
Self {
mutex: Mutex::new(false),
condvar: Condvar::new(),
}
}
fn wait(&self) {
let mut signaled = self.mutex.lock().unwrap();
while !*signaled {
signaled = self.condvar.wait(signaled).unwrap();
}
*signaled = false;
}
fn signal(&self) {
let mut signaled = self.mutex.lock().unwrap();
*signaled = true;
self.condvar.notify_one();
}
}
}