nio 0.1.4

Async runtime for Rust
Documentation
mod local;
mod runtime;

use std::{cell::UnsafeCell, rc::Rc};

use super::*;
use worker::WorkerId;

pub use local::LocalContext;
pub use runtime::RuntimeContext;

thread_local! {
    static CONTEXT: UnsafeCell<NioContext> = const { UnsafeCell::new(NioContext::None) };
}

#[derive(Clone)]
pub enum NioContext {
    None,
    Runtime(Arc<RuntimeContext>),
    Local(Rc<LocalContext>),
}

impl NioContext {
    #[inline(never)]
    fn panic_if_exist(&self) {
        match self {
            NioContext::Runtime(_) => panic!("global runtime already exist"),
            NioContext::Local(_) => panic!("local runtime already exist"),
            NioContext::None => {}
        }
    }

    #[inline(never)]
    fn panic_if_local_ctx_not_found(&self) {
        match self {
            NioContext::Runtime(_) => panic!("expected local runtime, found global runtime"),
            NioContext::None => panic!("no local runtime exist"),
            NioContext::Local(_) => {}
        }
    }

    fn init(local: Rc<LocalContext>) {
        CONTEXT.with(|ctx| unsafe {
            (*ctx.get()).panic_if_exist();
            *ctx.get() = NioContext::Local(local)
        });
    }

    pub fn drop_local_context() {
        CONTEXT.with(|ctx| unsafe {
            (*ctx.get()).panic_if_local_ctx_not_found();
            *ctx.get() = NioContext::None
        });
    }

    fn enter(rt: Arc<RuntimeContext>) {
        CONTEXT.with(|ctx| unsafe {
            (*ctx.get()).panic_if_exist();
            *ctx.get() = NioContext::Runtime(rt)
        });
    }

    pub fn get<F, R>(f: F) -> R
    where
        F: FnOnce(&NioContext) -> R,
    {
        CONTEXT.with(|ctx| unsafe { f(&*ctx.get()) })
    }
}

#[inline(never)]
pub fn no_rt_found_panic() -> ! {
    panic!("no `Nio` runtime available");
}

#[inline(never)]
pub fn no_local_rt_found_panic() -> ! {
    panic!("no `Nio` local runtime found");
}