mod atomic_waker;
use crate::Result;
use std::cell::Cell;
use std::future::Future;
use std::ptr;
thread_local! {
static RUNTIME: Cell<*const Runtime> = Cell::new(ptr::null());
}
cfg_events_driver! {
pub(crate) mod events;
#[doc(hidden)]
pub use self::events::EventsDriver;
pub(crate) fn with_events<F, T>(f: F) -> T where F: FnOnce(&EventsDriver) -> T {
RUNTIME.with(|rt| {
let rt = unsafe { rt.get().as_ref().expect("missing audio runtime") };
f(&rt.events)
})
}
}
cfg_poll_driver! {
pub(crate) mod poll;
#[doc(hidden)]
pub use self::poll::{PollDriver, AsyncPoll};
pub(crate) fn with_poll<F, T>(f: F) -> T where F: FnOnce(&PollDriver) -> T {
RUNTIME.with(|rt| {
let rt = unsafe { rt.get().as_ref().expect("missing audio runtime") };
f(&rt.poll)
})
}
}
pub struct Runtime {
#[cfg(feature = "events-driver")]
events: self::events::EventsDriver,
#[cfg(feature = "poll-driver")]
poll: self::poll::PollDriver,
}
impl Runtime {
pub fn new() -> Result<Self> {
Ok(Self {
#[cfg(feature = "events-driver")]
events: self::events::EventsDriver::new()?,
#[cfg(feature = "poll-driver")]
poll: self::poll::PollDriver::new()?,
})
}
pub fn enter(&self) -> RuntimeGuard<'_> {
let old = RUNTIME.with(|rt| rt.replace(self as *const _));
RuntimeGuard {
_runtime: self,
old,
}
}
pub async fn wrap<F>(&self, f: F) -> F::Output
where
F: Future,
{
use std::pin::Pin;
use std::task::{Context, Poll};
return GuardFuture(self, f).await;
struct GuardFuture<'a, F>(&'a Runtime, F);
impl<'a, F> Future for GuardFuture<'a, F>
where
F: Future,
{
type Output = F::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let _guard = self.0.enter();
let future = unsafe { Pin::map_unchecked_mut(self, |this| &mut this.1) };
future.poll(cx)
}
}
}
pub fn join(self) {
#[cfg(feature = "events-driver")]
let _ = self.events.join();
#[cfg(feature = "poll-driver")]
let _ = self.poll.join();
}
}
pub struct RuntimeGuard<'a> {
_runtime: &'a Runtime,
old: *const Runtime,
}
impl Drop for RuntimeGuard<'_> {
fn drop(&mut self) {
RUNTIME.with(|rt| {
rt.set(self.old);
})
}
}