task_local context over context objects

- interner impls logically separate from API in orchid-base (default host interner still in base for testing)
- error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options
- no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited
- still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
2026-01-01 14:54:29 +00:00
parent 06debb3636
commit 32d6237dc5
92 changed files with 2507 additions and 2223 deletions

View File

@@ -10,12 +10,13 @@ use hashbrown::HashSet;
use orchid_base::error::OrcErrv;
use orchid_base::format::{FmtCtx, FmtUnit, Format};
use orchid_base::location::Pos;
use orchid_base::reqnot::Requester;
use orchid_base::stash::stash;
use crate::api;
use crate::atom::ForeignAtom;
use crate::context::{ctx, i};
use crate::entrypoint::{notify, request};
use crate::gen_expr::{GExpr, GExprKind};
use crate::system::sys_id;
pub struct BorrowedExprStore(RefCell<Option<HashSet<Rc<ExprHandle>>>>);
impl BorrowedExprStore {
@@ -73,7 +74,7 @@ impl ExprHandle {
/// to lend the expr, and you expect the receiver to use
/// [ExprHandle::borrowed] or [ExprHandle::from_ticket]
pub fn ticket(&self) -> api::ExprTicket { self.0 }
async fn send_acq(&self) { ctx().reqnot().notify(api::Acquire(ctx().sys_id(), self.0)).await }
async fn send_acq(&self) { notify(api::Acquire(sys_id(), self.0)).await }
/// If this is the last one reference, do nothing, otherwise send an Acquire
pub async fn on_borrow_expire(self: Rc<Self>) { self.serialize().await; }
/// Drop the handle and get the ticket without a release notification.
@@ -94,8 +95,8 @@ impl fmt::Debug for ExprHandle {
}
impl Drop for ExprHandle {
fn drop(&mut self) {
let notif = api::Release(ctx().sys_id(), self.0);
ctx().spawn(async move { ctx().reqnot().clone().notify(notif).await })
let notif = api::Release(sys_id(), self.0);
stash(async move { notify(notif).await })
}
}
@@ -117,12 +118,12 @@ impl Expr {
}
pub async fn data(&self) -> &ExprData {
(self.data.get_or_init(async {
let details = ctx().reqnot().request(api::Inspect { target: self.handle.ticket() }).await;
let pos = Pos::from_api(&details.location, &i()).await;
let details = request(api::Inspect { target: self.handle.ticket() }).await;
let pos = Pos::from_api(&details.location).await;
let kind = match details.kind {
api::InspectedKind::Atom(a) =>
ExprKind::Atom(ForeignAtom::new(self.handle.clone(), a, pos.clone())),
api::InspectedKind::Bottom(b) => ExprKind::Bottom(OrcErrv::from_api(&b, &i()).await),
api::InspectedKind::Bottom(b) => ExprKind::Bottom(OrcErrv::from_api(&b).await),
api::InspectedKind::Opaque => ExprKind::Opaque,
};
ExprData { pos, kind }
@@ -150,8 +151,7 @@ impl Format for Expr {
match &self.data().await.kind {
ExprKind::Opaque => "OPAQUE".to_string().into(),
ExprKind::Bottom(b) => format!("Bottom({b})").into(),
ExprKind::Atom(a) =>
FmtUnit::from_api(&ctx().reqnot().request(api::ExtAtomPrint(a.atom.clone())).await),
ExprKind::Atom(a) => FmtUnit::from_api(&request(api::ExtAtomPrint(a.atom.clone())).await),
}
}
}