exec working up to halt
clean shutdown doesn't for some reason
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
|
||||
use async_once_cell::OnceCell;
|
||||
use derive_destructure::destructure;
|
||||
use orchid_api::ExtAtomPrint;
|
||||
use hashbrown::HashSet;
|
||||
use orchid_base::error::OrcErrv;
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format};
|
||||
use orchid_base::location::Pos;
|
||||
@@ -14,26 +16,61 @@ use crate::atom::ForeignAtom;
|
||||
use crate::gen_expr::{GExpr, GExprKind};
|
||||
use crate::system::SysCtx;
|
||||
|
||||
pub struct BorrowedExprStore(RefCell<Option<HashSet<Rc<ExprHandle>>>>);
|
||||
impl BorrowedExprStore {
|
||||
pub(crate) fn new() -> Self { Self(RefCell::new(Some(HashSet::new()))) }
|
||||
pub async fn dispose(self) {
|
||||
let elements = self.0.borrow_mut().take().unwrap();
|
||||
for handle in elements {
|
||||
handle.drop_one().await
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Drop for BorrowedExprStore {
|
||||
fn drop(&mut self) {
|
||||
if self.0.borrow().is_some() {
|
||||
panic!("This should always be explicitly disposed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(destructure)]
|
||||
pub struct ExprHandle {
|
||||
pub tk: api::ExprTicket,
|
||||
pub ctx: SysCtx,
|
||||
}
|
||||
impl ExprHandle {
|
||||
/// # Safety
|
||||
///
|
||||
/// This function does not signal to take ownership of the expr. It must only
|
||||
/// be called on tickets that are already implicitly owned.
|
||||
pub unsafe fn from_args(ctx: SysCtx, tk: api::ExprTicket) -> Self { Self { ctx, tk } }
|
||||
/// This function does not signal to take ownership of the expr.
|
||||
pub fn borrowed(ctx: SysCtx, tk: api::ExprTicket, store: &BorrowedExprStore) -> Rc<Self> {
|
||||
let this = Rc::new(Self { ctx, tk });
|
||||
store.0.borrow_mut().as_mut().unwrap().insert(this.clone());
|
||||
this
|
||||
}
|
||||
pub fn deserialize(ctx: SysCtx, tk: api::ExprTicket) -> Rc<Self> { Rc::new(Self { ctx, tk }) }
|
||||
pub fn get_ctx(&self) -> SysCtx { self.ctx.clone() }
|
||||
pub async fn clone(&self) -> Self {
|
||||
self.ctx.reqnot().notify(api::Acquire(self.ctx.sys_id(), self.tk)).await;
|
||||
Self { ctx: self.ctx.clone(), tk: self.tk }
|
||||
/// Drop one instance of the handle silently; if it's the last one, do
|
||||
/// nothing, otherwise send an Acquire
|
||||
pub async fn drop_one(self: Rc<Self>) {
|
||||
if let Err(rc) = Rc::try_unwrap(self) {
|
||||
rc.ctx.reqnot().notify(api::Acquire(rc.ctx.sys_id(), rc.tk)).await
|
||||
}
|
||||
}
|
||||
/// Drop the handle and get the ticket without a release notification.
|
||||
/// Use this with messages that imply ownership transfer. This function is
|
||||
/// safe because abusing it is a memory leak.
|
||||
pub fn into_tk(self) -> api::ExprTicket { self.destructure().0 }
|
||||
pub fn serialize(self) -> api::ExprTicket { self.destructure().0 }
|
||||
}
|
||||
impl Eq for ExprHandle {}
|
||||
impl PartialEq for ExprHandle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.ctx.sys_id() == other.ctx.sys_id() && self.tk == other.tk
|
||||
}
|
||||
}
|
||||
impl Hash for ExprHandle {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.ctx.sys_id().hash(state);
|
||||
self.tk.hash(state);
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for ExprHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@@ -92,8 +129,9 @@ 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(&self.handle.ctx.reqnot().request(ExtAtomPrint(a.atom.clone())).await),
|
||||
ExprKind::Atom(a) => FmtUnit::from_api(
|
||||
&self.handle.ctx.reqnot().request(api::ExtAtomPrint(a.atom.clone())).await,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user