Separated orchid-host and orchid-extension
This is an architectural change that allows me to implment specifics first and generalize along observed symmetries in orchid-base
This commit is contained in:
137
orchid-extension/src/data.rs
Normal file
137
orchid-extension/src/data.rs
Normal file
@@ -0,0 +1,137 @@
|
||||
use std::any::TypeId;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use itertools::Itertools;
|
||||
use orchid_api::expr::Expr;
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::{NewSystem, SysId, SystemDecl};
|
||||
use orchid_api_traits::Coding;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
use ordered_float::NotNan;
|
||||
|
||||
pub struct SystemHandle<T: SystemDepCard> {
|
||||
_t: PhantomData<T>,
|
||||
id: SysId,
|
||||
reqnot: ReqNot<ExtMsgSet>,
|
||||
}
|
||||
impl<T: SystemDepCard> SystemHandle<T> {
|
||||
fn new(id: SysId, reqnot: ReqNot<ExtMsgSet>) -> Self { Self { _t: PhantomData, id, reqnot } }
|
||||
}
|
||||
|
||||
pub trait System: Send {
|
||||
fn consts(&self) -> Expr;
|
||||
}
|
||||
|
||||
pub struct SystemParams<Ctor: SystemCtor + ?Sized> {
|
||||
pub deps: <Ctor::Deps as DepSet>::Sat,
|
||||
pub id: SysId,
|
||||
pub reqnot: ReqNot<ExtMsgSet>,
|
||||
}
|
||||
|
||||
pub trait SystemDepCard {
|
||||
type IngressReq: Coding;
|
||||
type IngressNotif: Coding;
|
||||
const NAME: &'static str;
|
||||
}
|
||||
|
||||
pub trait DepSet {
|
||||
type Sat;
|
||||
fn report(names: &mut impl FnMut(&'static str));
|
||||
fn create(take: &mut impl FnMut() -> SysId, reqnot: ReqNot<ExtMsgSet>) -> Self::Sat;
|
||||
}
|
||||
|
||||
impl<T: SystemDepCard> DepSet for T {
|
||||
type Sat = SystemHandle<Self>;
|
||||
fn report(names: &mut impl FnMut(&'static str)) { names(T::NAME) }
|
||||
fn create(take: &mut impl FnMut() -> SysId, reqnot: ReqNot<ExtMsgSet>) -> Self::Sat {
|
||||
SystemHandle::new(take(), reqnot)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SystemCtor: Send {
|
||||
type Deps: DepSet;
|
||||
const NAME: &'static str;
|
||||
const VERSION: f64;
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(params: SystemParams<Self>) -> Box<dyn System>;
|
||||
}
|
||||
|
||||
pub trait DynSystemCtor: Send {
|
||||
fn decl(&self) -> SystemDecl;
|
||||
fn new_system(&self, new: &NewSystem, reqnot: ReqNot<ExtMsgSet>) -> Box<dyn System>;
|
||||
}
|
||||
|
||||
impl<T: SystemCtor + 'static> DynSystemCtor for T {
|
||||
fn decl(&self) -> SystemDecl {
|
||||
// Version is equivalent to priority for all practical purposes
|
||||
let priority = NotNan::new(T::VERSION).unwrap();
|
||||
// aggregate depends names
|
||||
let mut depends = Vec::new();
|
||||
T::Deps::report(&mut |n| depends.push(n.to_string()));
|
||||
// generate definitely unique id
|
||||
let mut ahash = ahash::AHasher::default();
|
||||
TypeId::of::<T>().hash(&mut ahash);
|
||||
let id = (ahash.finish().to_be_bytes().into_iter().tuples())
|
||||
.map(|(l, b)| u16::from_be_bytes([l, b]))
|
||||
.fold(0, |a, b| a ^ b);
|
||||
SystemDecl { name: T::NAME.to_string(), depends, id, priority }
|
||||
}
|
||||
fn new_system(&self, new: &NewSystem, reqnot: ReqNot<ExtMsgSet>) -> Box<dyn System> {
|
||||
let mut ids = new.depends.iter().copied();
|
||||
T::new(SystemParams {
|
||||
deps: T::Deps::create(&mut || ids.next().unwrap(), reqnot.clone()),
|
||||
id: new.id,
|
||||
reqnot,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExtensionData {
|
||||
pub systems: Vec<Box<dyn DynSystemCtor>>,
|
||||
}
|
||||
|
||||
mod dep_set_tuple_impls {
|
||||
use orchid_api::proto::ExtMsgSet;
|
||||
use orchid_api::system::SysId;
|
||||
use orchid_base::reqnot::ReqNot;
|
||||
|
||||
use super::DepSet;
|
||||
|
||||
macro_rules! dep_set_tuple_impl {
|
||||
($($name:ident),*) => {
|
||||
impl<$( $name :DepSet ),*> DepSet for ( $( $name , )* ) {
|
||||
type Sat = ( $( $name ::Sat , )* );
|
||||
fn report(names: &mut impl FnMut(&'static str)) {
|
||||
$(
|
||||
$name ::report(names);
|
||||
)*
|
||||
}
|
||||
fn create(take: &mut impl FnMut() -> SysId, reqnot: ReqNot<ExtMsgSet>) -> Self::Sat {
|
||||
(
|
||||
$(
|
||||
$name ::create(take, reqnot.clone()),
|
||||
)*
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dep_set_tuple_impl!(A);
|
||||
dep_set_tuple_impl!(A, B); // 2
|
||||
dep_set_tuple_impl!(A, B, C);
|
||||
dep_set_tuple_impl!(A, B, C, D); // 4
|
||||
dep_set_tuple_impl!(A, B, C, D, E);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H); // 8
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L); // 12
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
dep_set_tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); // 16
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use orchid_api::proto::{ExtMsgSet, ExtensionHeader, HostExtNotif, HostExtReq, HostHeader};
|
||||
use orchid_api_traits::{Decode, Encode};
|
||||
use orchid_base::child::{recv_parent_msg, send_parent_msg};
|
||||
use orchid_base::clone;
|
||||
use orchid_base::intern::{init_replica, sweep_replica};
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
|
||||
pub struct ExtensionData {}
|
||||
use crate::data::ExtensionData;
|
||||
use crate::msg::{recv_parent_msg, send_parent_msg};
|
||||
|
||||
pub fn main(data: &mut ExtensionData) {
|
||||
pub fn main(data: ExtensionData) {
|
||||
HostHeader::decode(&mut &recv_parent_msg().unwrap()[..]);
|
||||
let mut buf = Vec::new();
|
||||
ExtensionHeader { systems: vec![] }.encode(&mut buf);
|
||||
let decls = data.systems.iter().map(|sys| sys.decl()).collect_vec();
|
||||
let systems = Arc::new(Mutex::new(HashMap::new()));
|
||||
ExtensionHeader { systems: decls.clone() }.encode(&mut buf);
|
||||
send_parent_msg(&buf).unwrap();
|
||||
let exiting = Arc::new(AtomicBool::new(false));
|
||||
let rn = ReqNot::<ExtMsgSet>::new(
|
||||
@@ -22,11 +26,17 @@ pub fn main(data: &mut ExtensionData) {
|
||||
HostExtNotif::Exit => exiting.store(true, Ordering::Relaxed),
|
||||
_ => todo!(),
|
||||
}),
|
||||
|req| match req.req() {
|
||||
clone!(systems; move |req| match req.req() {
|
||||
HostExtReq::Ping(ping) => req.handle(ping, &()),
|
||||
HostExtReq::Sweep(sweep) => req.handle(sweep, &sweep_replica()),
|
||||
HostExtReq::NewSystem(new_sys) => {
|
||||
let i = decls.iter().enumerate().find(|(_, s)| s.id == new_sys.system).unwrap().0;
|
||||
let system = data.systems[i].new_system(new_sys, req.reqnot());
|
||||
systems.lock().unwrap().insert(new_sys.id, system);
|
||||
req.handle(new_sys, &())
|
||||
},
|
||||
_ => todo!(),
|
||||
},
|
||||
}),
|
||||
);
|
||||
init_replica(rn.clone().map());
|
||||
while !exiting.load(Ordering::Relaxed) {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use orchid_api::proto::{ExtMsgSet, ExtensionHeader, HostExtNotif, HostExtReq, HostHeader};
|
||||
use orchid_api_traits::{Decode, Encode};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::child::{recv_parent_msg, send_parent_msg};
|
||||
use crate::clone;
|
||||
use crate::intern::{init_replica, sweep_replica};
|
||||
use crate::reqnot::{ReqNot, Requester as _};
|
||||
|
||||
pub struct SystemParams {
|
||||
deps: Vec<SystemHandle>,
|
||||
|
||||
}
|
||||
|
||||
pub struct SystemCtor {
|
||||
deps: Vec<String>,
|
||||
make: Box<dyn FnMut(SystemParams) -> System>,
|
||||
name: String,
|
||||
prio: NotNan<f64>,
|
||||
dependencies: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct ExtensionData {
|
||||
systems: Vec<SystemCtor>
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
pub mod entrypoint;
|
||||
pub mod data;
|
||||
pub mod msg;
|
||||
|
||||
6
orchid-extension/src/msg.rs
Normal file
6
orchid-extension/src/msg.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use std::io;
|
||||
|
||||
use orchid_base::msg::{recv_msg, send_msg};
|
||||
|
||||
pub fn send_parent_msg(msg: &[u8]) -> io::Result<()> { send_msg(&mut io::stdout().lock(), msg) }
|
||||
pub fn recv_parent_msg() -> io::Result<Vec<u8>> { recv_msg(&mut io::stdin().lock()) }
|
||||
Reference in New Issue
Block a user