Correctly halts
This commit is contained in:
@@ -8,6 +8,7 @@ use std::sync::atomic::AtomicU64;
|
||||
|
||||
use async_lock::{RwLock, RwLockReadGuard};
|
||||
use async_once_cell::OnceCell;
|
||||
use dyn_clone::{DynClone, clone_box};
|
||||
use futures::future::{LocalBoxFuture, ready};
|
||||
use futures::{AsyncRead, AsyncWrite, FutureExt};
|
||||
use itertools::Itertools;
|
||||
@@ -15,7 +16,7 @@ use memo_map::MemoMap;
|
||||
use never::Never;
|
||||
use orchid_api_traits::{Decode, Encode, enc_vec};
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::format::{FmtCtx, FmtCtxImpl, FmtUnit};
|
||||
use orchid_base::format::{FmtCtx, FmtCtxImpl, FmtUnit, take_first};
|
||||
use orchid_base::name::Sym;
|
||||
|
||||
use crate::api;
|
||||
@@ -39,8 +40,10 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
|
||||
let (typ_id, _) = get_info::<A>(ctx.get::<CtedObj>().inst().card());
|
||||
let mut data = enc_vec(&typ_id).await;
|
||||
self.encode(Pin::<&mut Vec<u8>>::new(&mut data)).await;
|
||||
ctx.get_or_default::<ObjStore>().objects.read().await.insert(atom_id, Box::new(self));
|
||||
api::Atom { drop: Some(atom_id), data, owner: ctx.sys_id() }
|
||||
let g = ctx.get_or_default::<ObjStore>().objects.read().await;
|
||||
g.insert(atom_id, Box::new(self));
|
||||
std::mem::drop(g);
|
||||
api::Atom { drop: Some(atom_id), data: api::AtomData(data), owner: ctx.sys_id() }
|
||||
})
|
||||
}
|
||||
fn _info() -> Self::_Info { OwnedAtomDynfo { msbuild: A::reg_reqs(), ms: OnceCell::new() } }
|
||||
@@ -55,8 +58,10 @@ pub(crate) struct AtomReadGuard<'a> {
|
||||
impl<'a> AtomReadGuard<'a> {
|
||||
async fn new(id: api::AtomId, ctx: &'a SysCtx) -> Self {
|
||||
let guard = ctx.get_or_default::<ObjStore>().objects.read().await;
|
||||
let valid = guard.iter().map(|i| i.0).collect_vec();
|
||||
assert!(guard.get(&id).is_some(), "Received invalid atom ID: {id:?} not in {valid:?}");
|
||||
if guard.get(&id).is_none() {
|
||||
let valid = guard.iter().map(|i| i.0).collect_vec();
|
||||
panic!("Received invalid atom ID: {id:?} not in {valid:?}");
|
||||
}
|
||||
Self { id, guard }
|
||||
}
|
||||
}
|
||||
@@ -257,7 +262,7 @@ fn assert_serializable<T: OwnedAtom>() {
|
||||
assert_ne!(TypeId::of::<T::Refs>(), TypeId::of::<Never>(), "{MSG}");
|
||||
}
|
||||
|
||||
pub trait DynOwnedAtom: 'static {
|
||||
pub trait DynOwnedAtom: DynClone + 'static {
|
||||
fn atom_tid(&self) -> TypeId;
|
||||
fn as_any_ref(&self) -> &dyn Any;
|
||||
fn encode<'a>(&'a self, buffer: Pin<&'a mut dyn AsyncWrite>) -> LocalBoxFuture<'a, ()>;
|
||||
@@ -306,16 +311,38 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ObjStore {
|
||||
next_id: AtomicU64,
|
||||
objects: RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
|
||||
pub(crate) struct ObjStore {
|
||||
pub(crate) next_id: AtomicU64,
|
||||
pub(crate) objects: RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
|
||||
}
|
||||
impl SysCtxEntry for ObjStore {}
|
||||
|
||||
pub async fn own<A: OwnedAtom>(typ: TypAtom<A>) -> A {
|
||||
let ctx = typ.untyped.ctx();
|
||||
let g = ctx.get_or_default::<ObjStore>().objects.read().await;
|
||||
let dyn_atom = (g.get(&typ.untyped.atom.drop.expect("Owned atoms always have a drop ID")))
|
||||
.expect("Atom ID invalid; atom type probably not owned by this crate");
|
||||
let atom_id = typ.untyped.atom.drop.expect("Owned atoms always have a drop ID");
|
||||
let dyn_atom =
|
||||
g.get(&atom_id).expect("Atom ID invalid; atom type probably not owned by this crate");
|
||||
dyn_atom.as_any_ref().downcast_ref().cloned().expect("The ID should imply a type as well")
|
||||
}
|
||||
|
||||
pub async fn debug_print_obj_store(ctx: &SysCtx, show_atoms: bool) {
|
||||
let store = ctx.get_or_default::<ObjStore>();
|
||||
let keys = store.objects.read().await.keys().cloned().collect_vec();
|
||||
let mut message = "Atoms in store:".to_string();
|
||||
if !show_atoms {
|
||||
message += &keys.iter().map(|k| format!(" {:?}", k)).join("");
|
||||
} else {
|
||||
for k in keys {
|
||||
let g = store.objects.read().await;
|
||||
let Some(atom) = g.get(&k) else {
|
||||
message += &format!("\n{k:?} has since been deleted");
|
||||
continue;
|
||||
};
|
||||
let atom = clone_box(&**atom);
|
||||
std::mem::drop(g);
|
||||
message += &format!("\n{k:?} -> {}", take_first(&atom.dyn_print(ctx.clone()).await, true));
|
||||
}
|
||||
}
|
||||
eprintln!("{message}")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user