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

@@ -1,73 +1,48 @@
use std::borrow::Borrow;
use std::cell::RefCell;
use std::fmt::Debug;
use std::hash::Hash;
use std::rc::{Rc, Weak};
use std::rc::Rc;
use hashbrown::HashMap;
use orchid_api_traits::Coding;
use orchid_base::interner::{IStr, IStrHandle, IStrv, IStrvHandle};
use futures::future::{LocalBoxFuture, join_all, ready};
use itertools::Itertools;
use orchid_base::interner::local_interner::{Int, StrBranch, StrvBranch};
use orchid_base::interner::{IStr, IStrv, InternerSrv};
use crate::api;
use crate::entrypoint::request;
trait Branch: 'static {
type Token: Clone + Copy + Debug + Hash + PartialEq + Eq + PartialOrd + Ord + Coding + 'static;
type Data: 'static + Borrow<Self::Borrow>;
type Borrow: ToOwned<Owned = Self::Data> + ?Sized;
type Handle: AsRef<Self::Borrow>;
type Interned: Clone;
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned;
#[derive(Default)]
struct ExtInterner {
str: Int<StrBranch>,
strv: Int<StrvBranch>,
}
impl InternerSrv for ExtInterner {
fn is<'a>(&'a self, v: &'a str) -> LocalBoxFuture<'a, IStr> {
match self.str.i(v) {
Ok(i) => Box::pin(ready(i)),
Err(e) => Box::pin(async { e.set_if_empty(request(api::InternStr(v.to_owned())).await) }),
}
}
fn es(&self, t: api::TStr) -> LocalBoxFuture<'_, IStr> {
match self.str.e(t) {
Ok(i) => Box::pin(ready(i)),
Err(e) => Box::pin(async move { e.set_if_empty(Rc::new(request(api::ExternStr(t)).await)) }),
}
}
fn iv<'a>(&'a self, v: &'a [IStr]) -> LocalBoxFuture<'a, IStrv> {
match self.strv.i(v) {
Ok(i) => Box::pin(ready(i)),
Err(e) => Box::pin(async {
e.set_if_empty(request(api::InternStrv(v.iter().map(|is| is.to_api()).collect_vec())).await)
}),
}
}
fn ev(&self, t: orchid_api::TStrv) -> LocalBoxFuture<'_, IStrv> {
match self.strv.e(t) {
Ok(i) => Box::pin(ready(i)),
Err(e) => Box::pin(async move {
let tstr_v = request(api::ExternStrv(t)).await;
e.set_if_empty(Rc::new(join_all(tstr_v.into_iter().map(|t| self.es(t))).await))
}),
}
}
}
struct StrBranch;
impl Branch for StrBranch {
type Data = String;
type Token = api::TStr;
type Borrow = str;
type Handle = Handle<Self>;
type Interned = IStr;
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned { IStr(t, h) }
}
struct StrvBranch;
impl Branch for StrvBranch {
type Data = Vec<IStr>;
type Token = api::TStrv;
type Borrow = [IStr];
type Handle = Handle<Self>;
type Interned = IStrv;
fn mk_interned(t: Self::Token, h: Rc<Self::Handle>) -> Self::Interned { IStrv(t, h) }
}
struct Data<B: Branch> {
token: B::Token,
data: Rc<B::Data>,
}
struct Handle<B: Branch> {
data: Rc<Data<B>>,
parent: Weak<RefCell<IntData<B>>>,
}
impl IStrHandle for Handle<StrBranch> {}
impl AsRef<str> for Handle<StrBranch> {
fn as_ref(&self) -> &str { self.data.data.as_ref().as_ref() }
}
impl IStrvHandle for Handle<StrvBranch> {}
impl AsRef<[IStr]> for Handle<StrvBranch> {
fn as_ref(&self) -> &[IStr] { self.data.data.as_ref().as_ref() }
}
struct Rec<B: Branch> {
handle: Weak<B::Handle>,
data: Rc<Data<B>>,
}
struct IntData<B: Branch> {
by_tok: HashMap<B::Token, Rec<B>>,
by_data: HashMap<Rc<B::Data>, Rec<B>>,
}
impl<B: Branch> IntData<B> {
async fn i(&mut self, q: &B::Borrow) -> B::Interned { todo!() }
async fn e(&mut self, q: &B::Token) -> B::Interned { todo!() }
}
struct Int<B: Branch>(Rc<RefCell<IntData<B>>>);
pub fn new_interner() -> Rc<dyn InternerSrv> { Rc::<ExtInterner>::default() }