Typed Refs (!). Decent speedup by avoiding marshalling

This commit is contained in:
Tony Garnock-Jones 2021-07-22 16:53:56 +02:00
parent f0a9894ee8
commit d85b980834
19 changed files with 623 additions and 598 deletions

View File

@ -1,6 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use std::any::Any;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicU64; use std::sync::atomic::AtomicU64;
@ -29,10 +28,7 @@ fn says(who: _Any, what: _Any) -> _Any {
struct ShutdownEntity; struct ShutdownEntity;
impl Entity for ShutdownEntity { impl Entity<_Any> for ShutdownEntity {
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn message(&mut self, t: &mut Activation, _m: _Any) -> ActorResult { fn message(&mut self, t: &mut Activation, _m: _Any) -> ActorResult {
t.actor.shutdown(); t.actor.shutdown();
Ok(()) Ok(())
@ -63,12 +59,12 @@ pub fn bench_pub(c: &mut Criterion) {
ac.linked_task(syndicate::name!("sender"), async move { ac.linked_task(syndicate::name!("sender"), async move {
for _ in 0..iters { for _ in 0..iters {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
external_event(&Arc::clone(&ds), &debtor, Box::new( external_event(&Arc::clone(&ds.mailbox), &debtor, Box::new(
move |t| ds.with_entity( move |t| ds.with_entity(
|e| e.message(t, says(_Any::new("bench_pub"), |e| e.message(t, says(_Any::new("bench_pub"),
Value::ByteString(vec![]).wrap())))))? Value::ByteString(vec![]).wrap())))))?
} }
external_event(&Arc::clone(&shutdown), &debtor, Box::new( external_event(&Arc::clone(&shutdown.mailbox), &debtor, Box::new(
move |t| shutdown.with_entity( move |t| shutdown.with_entity(
|e| e.message(t, _Any::new(true)))))?; |e| e.message(t, _Any::new(true)))))?;
Ok(()) Ok(())
@ -83,14 +79,11 @@ pub fn bench_pub(c: &mut Criterion) {
b.iter_custom(|iters| { b.iter_custom(|iters| {
let start = Instant::now(); let start = Instant::now();
rt.block_on(async move { rt.block_on(async move {
let ds = Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new()); let ds = Cap::new(&Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new()));
let turn_count = Arc::new(AtomicU64::new(0)); let turn_count = Arc::new(AtomicU64::new(0));
struct Receiver(Arc<AtomicU64>); struct Receiver(Arc<AtomicU64>);
impl Entity for Receiver { impl Entity<_Any> for Receiver {
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn message(&mut self, _t: &mut Activation, _m: _Any) -> ActorResult { fn message(&mut self, _t: &mut Activation, _m: _Any) -> ActorResult {
self.0.fetch_add(1, Ordering::Relaxed); self.0.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
@ -98,13 +91,13 @@ pub fn bench_pub(c: &mut Criterion) {
} }
let mut ac = Actor::new(); let mut ac = Actor::new();
let shutdown = ac.create(ShutdownEntity); let shutdown = Cap::new(&ac.create(ShutdownEntity));
let receiver = ac.create(Receiver(Arc::clone(&turn_count))); let receiver = Cap::new(&ac.create(Receiver(Arc::clone(&turn_count))));
{ {
let iters = iters.clone(); let iters = iters.clone();
ac.boot(syndicate::name!("dataspace"), move |t| Box::pin(async move { ac.boot(syndicate::name!("dataspace"), move |t| Box::pin(async move {
t.assert(&ds, &Observe { ds.assert(t, &Observe {
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
ctor: Box::new(p::CRec { ctor: Box::new(p::CRec {
label: Value::symbol("Says").wrap(), label: Value::symbol("Says").wrap(),
@ -122,7 +115,7 @@ pub fn bench_pub(c: &mut Criterion) {
})), })),
observer: receiver, observer: receiver,
}); });
t.assert(&ds, &Observe { ds.assert(t, &Observe {
pattern: p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::DBind(Box::new(p::DBind {
name: "shutdownTrigger".to_owned(), name: "shutdownTrigger".to_owned(),
pattern: p::Pattern::DLit(Box::new(p::DLit { pattern: p::Pattern::DLit(Box::new(p::DLit {
@ -135,15 +128,15 @@ pub fn bench_pub(c: &mut Criterion) {
t.actor.linked_task(syndicate::name!("sender"), async move { t.actor.linked_task(syndicate::name!("sender"), async move {
for _ in 0..iters { for _ in 0..iters {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
external_event(&Arc::clone(&ds), &debtor, Box::new( external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
move |t| ds.with_entity( move |t| ds.underlying.with_entity(
|e| e.message(t, says(_Any::new("bench_pub"), |e| e.message(t, says(_Any::new("bench_pub"),
Value::ByteString(vec![]).wrap())))))? Value::ByteString(vec![]).wrap())))))?
} }
{ {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
external_event(&Arc::clone(&ds), &debtor, Box::new( external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
move |t| ds.with_entity( move |t| ds.underlying.with_entity(
|e| e.message(t, _Any::new(true)))))?; |e| e.message(t, _Any::new(true)))))?;
} }
Ok(()) Ok(())

View File

@ -11,8 +11,7 @@ fn main() -> Result<(), Error> {
let mut c = CompilerConfig::new(gen_dir, "crate::schemas".to_owned()); let mut c = CompilerConfig::new(gen_dir, "crate::schemas".to_owned());
c.module_aliases.insert(vec!["EntityRef".to_owned()], "crate::actor".to_owned()); c.module_aliases.insert(vec!["EntityRef".to_owned()], "crate::actor".to_owned());
let inputs = expand_inputs(&vec!["protocols/schema-bundle.bin".to_owned(), let inputs = expand_inputs(&vec!["protocols/schema-bundle.bin".to_owned()])?;
"local-protocols/schema-bundle.bin".to_owned()])?;
c.load_schemas_and_bundles(&inputs)?; c.load_schemas_and_bundles(&inputs)?;
compile(&c) compile(&c)
} }

View File

@ -32,7 +32,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split(); let (i, o) = TcpStream::connect("127.0.0.1:8001").await?.into_split();
relay::connect_stream(t, i, o, sturdyref, (), |_state, t, ds| { relay::connect_stream(t, i, o, sturdyref, (), |_state, t, ds| {
let consumer = syndicate::entity(0) let consumer = syndicate::entity(0)
.on_message(|message_count, _t, m| { .on_message(|message_count, _t, m: _Any| {
if m.value().is_boolean() { if m.value().is_boolean() {
tracing::info!("{:?} messages in the last second", message_count); tracing::info!("{:?} messages in the last second", message_count);
*message_count = 0; *message_count = 0;
@ -41,9 +41,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
Ok(()) Ok(())
}) })
.create(t.actor); .create_cap(t.actor);
t.assert(&ds, &Observe { ds.assert(t, &Observe {
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
ctor: Box::new(p::CRec { ctor: Box::new(p::CRec {
label: Value::symbol("Says").wrap(), label: Value::symbol("Says").wrap(),
@ -68,9 +68,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
loop { loop {
stats_timer.tick().await; stats_timer.tick().await;
let consumer = Arc::clone(&consumer); let consumer = Arc::clone(&consumer);
external_event(&Arc::clone(&consumer), external_event(&Arc::clone(&consumer.underlying.mailbox),
&Debtor::new(syndicate::name!("debtor")), &Debtor::new(syndicate::name!("debtor")),
Box::new(move |t| consumer.with_entity( Box::new(move |t| consumer.underlying.with_entity(
|e| e.message(t, _Any::new(true)))))?; |e| e.message(t, _Any::new(true)))))?;
} }
}); });

View File

@ -114,58 +114,60 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut rtt_ns_samples: Vec<u64> = vec![0; report_latency_every]; let mut rtt_ns_samples: Vec<u64> = vec![0; report_latency_every];
let mut rtt_batch_count: usize = 0; let mut rtt_batch_count: usize = 0;
let mut current_reply = None; let mut current_reply = None;
syndicate::entity(Arc::clone(&*INERT_REF)) let self_ref = t.actor.create_inert();
.on_message(move |self_ref, t, m| { self_ref.become_entity(
match m.value().as_boolean() { syndicate::entity(Arc::clone(&self_ref))
Some(true) => { .on_message(move |self_ref, t, m: _Any| {
tracing::info!("{:?} turns, {:?} events in the last second", match m.value().as_boolean() {
turn_counter, Some(true) => {
event_counter); tracing::info!("{:?} turns, {:?} events in the last second",
turn_counter = 0; turn_counter,
event_counter = 0; event_counter);
} turn_counter = 0;
Some(false) => { event_counter = 0;
current_reply = None; }
} Some(false) => {
None => { current_reply = None;
event_counter += 1; }
let bindings = m.value().to_sequence()?; None => {
let timestamp = &bindings[0]; event_counter += 1;
let padding = &bindings[1]; let bindings = m.value().to_sequence()?;
let timestamp = &bindings[0];
let padding = &bindings[1];
if should_echo || (report_latency_every == 0) { if should_echo || (report_latency_every == 0) {
t.message(&ds, simple_record2(&send_label, ds.message(t, simple_record2(&send_label,
timestamp.clone(), timestamp.clone(),
padding.clone())); padding.clone()));
} else { } else {
if let None = current_reply { if let None = current_reply {
turn_counter += 1; turn_counter += 1;
t.message_immediate_self(&self_ref, _Any::new(false)); t.message_immediate_self(&self_ref, _Any::new(false));
let rtt_ns = now() - timestamp.value().to_u64()?; let rtt_ns = now() - timestamp.value().to_u64()?;
rtt_ns_samples[rtt_batch_count] = rtt_ns; rtt_ns_samples[rtt_batch_count] = rtt_ns;
rtt_batch_count += 1; rtt_batch_count += 1;
if rtt_batch_count == report_latency_every { if rtt_batch_count == report_latency_every {
rtt_ns_samples.sort(); rtt_ns_samples.sort();
report_latencies(&rtt_ns_samples); report_latencies(&rtt_ns_samples);
rtt_batch_count = 0; rtt_batch_count = 0;
}
current_reply = Some(
simple_record2(&send_label,
Value::from(now()).wrap(),
padding.clone()));
} }
ds.message(t, current_reply.as_ref().expect("some reply").clone());
current_reply = Some(
simple_record2(&send_label,
Value::from(now()).wrap(),
padding.clone()));
} }
t.message(&ds, current_reply.as_ref().expect("some reply").clone());
} }
} }
} Ok(())
Ok(()) }));
}) Cap::new(&self_ref)
.create_rec(t.actor, |_ac, self_ref, e_ref| *self_ref = Arc::clone(e_ref))
}; };
t.assert(&ds, &Observe { ds.assert(t, &Observe {
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
ctor: Box::new(p::CRec { ctor: Box::new(p::CRec {
label: Value::symbol(recv_label).wrap(), label: Value::symbol(recv_label).wrap(),
@ -190,9 +192,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
loop { loop {
stats_timer.tick().await; stats_timer.tick().await;
let consumer = Arc::clone(&consumer); let consumer = Arc::clone(&consumer);
external_event(&Arc::clone(&consumer), external_event(&Arc::clone(&consumer.underlying.mailbox),
&Debtor::new(syndicate::name!("debtor")), &Debtor::new(syndicate::name!("debtor")),
Box::new(move |t| consumer.with_entity( Box::new(move |t| consumer.underlying.with_entity(
|e| e.message(t, _Any::new(true)))))?; |e| e.message(t, _Any::new(true)))))?;
} }
}); });
@ -211,10 +213,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for _ in 0..action_count { for _ in 0..action_count {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
let current_rec = current_rec.clone(); let current_rec = current_rec.clone();
events.push(Box::new(move |t| ds.with_entity( events.push(Box::new(move |t| ds.underlying.with_entity(
|e| e.message(t, current_rec)))); |e| e.message(t, current_rec))));
} }
external_events(&ds, &debtor, events)? external_events(&ds.underlying.mailbox, &debtor, events)?
} }
Ok(()) Ok(())
}); });

View File

@ -48,10 +48,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for _ in 0..action_count { for _ in 0..action_count {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
let padding = padding.clone(); let padding = padding.clone();
events.push(Box::new(move |t| ds.with_entity( events.push(Box::new(move |t| ds.underlying.with_entity(
|e| e.message(t, says(Value::from("producer").wrap(), padding))))); |e| e.message(t, says(Value::from("producer").wrap(), padding)))));
} }
external_events(&ds, &debtor, events)?; external_events(&ds.underlying.mailbox, &debtor, events)?;
} }
}); });
Ok(None) Ok(None)

View File

@ -60,10 +60,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
s.arrival_counter = 0; s.arrival_counter = 0;
s.departure_counter = 0; s.departure_counter = 0;
Ok(()) Ok(())
}).create(t.actor) }).create_cap(t.actor)
}; };
t.assert(&ds, &Observe { ds.assert(t, &Observe {
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
ctor: Box::new(p::CRec { ctor: Box::new(p::CRec {
label: Value::symbol("Present").wrap(), label: Value::symbol("Present").wrap(),
@ -84,9 +84,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
loop { loop {
stats_timer.tick().await; stats_timer.tick().await;
let consumer = Arc::clone(&consumer); let consumer = Arc::clone(&consumer);
external_event(&Arc::clone(&consumer), external_event(&Arc::clone(&consumer.underlying.mailbox),
&Debtor::new(syndicate::name!("debtor")), &Debtor::new(syndicate::name!("debtor")),
Box::new(move |t| consumer.with_entity( Box::new(move |t| consumer.underlying.with_entity(
|e| e.message(t, _Any::new(true)))))?; |e| e.message(t, _Any::new(true)))))?;
} }
}); });

View File

@ -33,14 +33,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
let presence = presence.clone(); let presence = presence.clone();
let handle = handle.clone(); let handle = handle.clone();
external_event(&Arc::clone(&ds), &debtor, Box::new( external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
move |t| ds.with_entity(|e| e.assert(t, presence, handle)))) move |t| ds.underlying.with_entity(|e| e.assert(t, presence, handle))))
}; };
let retract_e = || { let retract_e = || {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
let handle = handle.clone(); let handle = handle.clone();
external_event(&Arc::clone(&ds), &debtor, Box::new( external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
move |t| ds.with_entity(|e| e.retract(t, handle)))) move |t| ds.underlying.with_entity(|e| e.retract(t, handle))))
}; };
assert_e()?; assert_e()?;
loop { loop {

View File

@ -1,8 +0,0 @@
all: schema-bundle.bin
clean:
rm -f schema-bundle.bin
schema-bundle.bin: schemas/*.prs
preserves-schemac schemas/*.prs > $@.tmp
mv $@.tmp $@

View File

@ -1,3 +0,0 @@
´³bundle·µ³ tunnelRelay„´³schema·³version³ definitions·³Input´³orµµ±eof´³lit³eof„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³bs´³atom³
ByteString„„„„„„µ±segment´³rec´³lit³segment„´³tupleµ´³named³bs´³atom³
ByteString„„„„„„„„³Output´³rec´³lit³event„´³tupleµ´³named³oid´³refµ³sturdy„³Oid„„´³named³event´³refµ³internalProtocol„³Event„„„„„³SyncGc´³rec´³lit³sync-gc„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³ RelayProtocol´³orµµ±Input´³refµ„³Input„„µ±Output´³refµ„³Output„„µ±SyncGc´³refµ„³SyncGc„„µ±flush´³lit³flush„„„„„³ embeddedType´³refµ³ EntityRef„³Ref„„„„„

View File

@ -1,8 +0,0 @@
version 1 .
embeddedType EntityRef.Ref .
RelayProtocol = Input / Output / SyncGc / =flush .
Input = =eof / <packet @bs bytes> / <segment @bs bytes>.
Output = <event @oid sturdy.Oid @event internalProtocol.Event>.
SyncGc = <sync-gc @peer #!#t>.

View File

@ -13,14 +13,16 @@ use preserves::value::Domain;
use preserves::value::IOValue; use preserves::value::IOValue;
use preserves::value::Map; use preserves::value::Map;
use preserves::value::NestedValue; use preserves::value::NestedValue;
use preserves_schema::support::ParseError;
use std::any::Any;
use std::boxed::Box; use std::boxed::Box;
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use std::convert::TryFrom;
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;
use std::sync::RwLock; use std::sync::RwLock;
use std::sync::atomic::{AtomicI64, AtomicU64, AtomicUsize, Ordering}; use std::sync::Weak;
use std::sync::atomic::{AtomicI64, AtomicU64, Ordering};
use tokio::select; use tokio::select;
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver}; use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
@ -34,33 +36,33 @@ pub type Handle = u64;
pub type ActorResult = Result<(), Error>; pub type ActorResult = Result<(), Error>;
pub type ActorHandle = tokio::task::JoinHandle<ActorResult>; pub type ActorHandle = tokio::task::JoinHandle<ActorResult>;
pub trait Entity: Send + std::marker::Sync { pub struct Synced;
fn as_any(&mut self) -> &mut dyn Any;
fn assert(&mut self, _t: &mut Activation, _a: _Any, _h: Handle) -> ActorResult { pub trait Entity<M>: Send + Sync {
fn assert(&mut self, _t: &mut Activation, _a: M, _h: Handle) -> ActorResult {
Ok(()) Ok(())
} }
fn retract(&mut self, _t: &mut Activation, _h: Handle) -> ActorResult { fn retract(&mut self, _t: &mut Activation, _h: Handle) -> ActorResult {
Ok(()) Ok(())
} }
fn message(&mut self, _t: &mut Activation, _m: _Any) -> ActorResult { fn message(&mut self, _t: &mut Activation, _m: M) -> ActorResult {
Ok(()) Ok(())
} }
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult { fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
t.message(&peer, _Any::new(true)); t.message(&peer, Synced);
Ok(()) Ok(())
} }
fn turn_end(&mut self, _t: &mut Activation) -> ActorResult { fn turn_end(&mut self, _t: &mut Activation) -> ActorResult {
Ok(()) Ok(())
} }
fn exit_hook(&mut self, _t: &mut Activation, _exit_status: &ActorResult) -> ActorResult { fn exit_hook(&mut self, _t: &mut Activation, _exit_status: &Arc<ActorResult>) -> ActorResult {
Ok(()) Ok(())
} }
} }
enum Destination { enum Destination {
ImmediateSelf(Action), ImmediateSelf(Action),
Remote(Arc<Ref>, Action), Remote(Arc<Mailbox>, Action),
} }
type OutboundAssertions = Map<Handle, Destination>; type OutboundAssertions = Map<Handle, Destination>;
@ -98,84 +100,45 @@ enum SystemMessage {
pub struct Mailbox { pub struct Mailbox {
pub actor_id: ActorId, pub actor_id: ActorId,
pub mailbox_id: u64,
tx: UnboundedSender<SystemMessage>, tx: UnboundedSender<SystemMessage>,
mailbox_count: Arc<AtomicUsize>,
} }
pub struct Actor { pub struct Actor {
actor_id: ActorId, actor_id: ActorId,
tx: UnboundedSender<SystemMessage>, tx: UnboundedSender<SystemMessage>,
mailbox: Weak<Mailbox>,
rx: Option<UnboundedReceiver<SystemMessage>>, rx: Option<UnboundedReceiver<SystemMessage>>,
mailbox_count: Arc<AtomicUsize>,
outbound_assertions: OutboundAssertions, outbound_assertions: OutboundAssertions,
next_task_id: u64, next_task_id: u64,
linked_tasks: Map<u64, CancellationToken>, linked_tasks: Map<u64, CancellationToken>,
exit_hooks: Vec<Arc<Ref>>, exit_hooks: Vec<Action>,
exit_status: Option<Arc<ActorResult>>,
} }
pub struct ObjectAddress { pub struct Ref<M> {
pub mailbox: Mailbox, pub mailbox: Arc<Mailbox>,
pub target: RwLock<Box<dyn Entity>>, pub target: RwLock<Option<Box<dyn Entity<M>>>>,
} }
impl ObjectAddress { #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub fn oid(&self) -> usize { pub struct Cap {
std::ptr::addr_of!(*self) as usize pub underlying: Arc<Ref<_Any>>,
}
}
impl PartialEq for ObjectAddress {
fn eq(&self, other: &Self) -> bool {
self.oid() == other.oid()
}
}
impl Eq for ObjectAddress {}
impl std::hash::Hash for ObjectAddress {
fn hash<H>(&self, hash: &mut H) where H: std::hash::Hasher {
self.oid().hash(hash)
}
}
impl PartialOrd for ObjectAddress {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ObjectAddress {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.oid().cmp(&other.oid())
}
}
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Ref {
pub addr: Arc<ObjectAddress>,
pub attenuation: Vec<CheckedCaveat>, pub attenuation: Vec<CheckedCaveat>,
} }
pub struct Guard<M>
where
for<'a> &'a M: Into<_Any>,
for<'a> M: TryFrom<&'a _Any>,
{
underlying: Arc<Ref<M>>
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static NEXT_DEBTOR_ID: AtomicU64 = AtomicU64::new(4); static NEXT_DEBTOR_ID: AtomicU64 = AtomicU64::new(4);
preserves_schema::support::lazy_static! { preserves_schema::support::lazy_static! {
pub static ref INERT_REF: Arc<Ref> = {
struct InertEntity;
impl crate::actor::Entity for InertEntity {
fn as_any(&mut self) -> &mut dyn Any {
self
}
}
let mut ac = Actor::new();
let e = ac.create(InertEntity);
ac.boot(tracing::info_span!(parent: None, "INERT_REF"),
|t| Box::pin(ready(Ok(t.actor.shutdown()))));
e
};
pub static ref SYNDICATE_CREDIT: i64 = { pub static ref SYNDICATE_CREDIT: i64 = {
let credit = let credit =
std::env::var("SYNDICATE_CREDIT").unwrap_or("100".to_owned()) std::env::var("SYNDICATE_CREDIT").unwrap_or("100".to_owned())
@ -204,6 +167,23 @@ pub fn start_debt_reporter() {
})); }));
} }
impl TryFrom<&_Any> for Synced {
type Error = ParseError;
fn try_from(value: &_Any) -> Result<Self, Self::Error> {
if let Some(true) = value.value().as_boolean() {
Ok(Synced)
} else {
Err(ParseError::conformance_error("Synced"))
}
}
}
impl From<&Synced> for _Any {
fn from(_value: &Synced) -> Self {
_Any::new(true)
}
}
impl<'activation> Activation<'activation> { impl<'activation> Activation<'activation> {
pub fn new(actor: &'activation mut Actor, debtor: Arc<Debtor>) -> Self { pub fn new(actor: &'activation mut Actor, debtor: Arc<Debtor>) -> Self {
Activation { Activation {
@ -214,47 +194,43 @@ impl<'activation> Activation<'activation> {
} }
} }
fn immediate_oid(&self, r: &Arc<Ref>) { fn immediate_oid<M>(&self, r: &Arc<Ref<M>>) {
if r.addr.mailbox.actor_id != self.actor.actor_id { if r.mailbox.actor_id != self.actor.actor_id {
panic!("Cannot use immediate_self to send to remote peers"); panic!("Cannot use immediate_self to send to remote peers");
} }
} }
pub fn assert<M>(&mut self, r: &Arc<Ref>, a: M) -> Handle where M: Into<_Any> { pub fn assert<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, a: M) -> Handle {
let handle = crate::next_handle(); let handle = crate::next_handle();
if let Some(assertion) = r.rewrite(a.into()) { {
{ let r = Arc::clone(r);
let r = Arc::clone(r); self.queue_for(&r).push(Box::new(
self.queue_for(&r).push(Box::new( move |t| r.with_entity(|e| e.assert(t, a, handle))));
move |t| r.with_entity(|e| e.assert(t, assertion, handle)))); }
} {
{ let r = Arc::clone(r);
let r = Arc::clone(r); self.actor.outbound_assertions.insert(
self.actor.outbound_assertions.insert( handle,
handle, Destination::Remote(Arc::clone(&r.mailbox), Box::new(
Destination::Remote(Arc::clone(&r), Box::new( move |t| r.with_entity(|e| e.retract(t, handle)))));
move |t| r.with_entity(|e| e.retract(t, handle)))));
}
} }
handle handle
} }
pub fn assert_immediate_self<M>(&mut self, r: &Arc<Ref>, a: M) -> Handle where M: Into<_Any> { pub fn assert_immediate_self<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, a: M) -> Handle {
self.immediate_oid(r); self.immediate_oid(r);
let handle = crate::next_handle(); let handle = crate::next_handle();
if let Some(assertion) = r.rewrite(a.into()) { {
{ let r = Arc::clone(r);
let r = Arc::clone(r); self.immediate_self.push(Box::new(
self.immediate_self.push(Box::new( move |t| r.with_entity(|e| e.assert(t, a, handle))));
move |t| r.with_entity(|e| e.assert(t, assertion, handle)))); }
} {
{ let r = Arc::clone(r);
let r = Arc::clone(r); self.actor.outbound_assertions.insert(
self.actor.outbound_assertions.insert( handle,
handle, Destination::ImmediateSelf(Box::new(
Destination::ImmediateSelf(Box::new( move |t| r.with_entity(|e| e.retract(t, handle)))));
move |t| r.with_entity(|e| e.retract(t, handle)))));
}
} }
handle handle
} }
@ -267,39 +243,39 @@ impl<'activation> Activation<'activation> {
fn retract_known_ref(&mut self, d: Destination) { fn retract_known_ref(&mut self, d: Destination) {
match d { match d {
Destination::Remote(r, action) => Destination::Remote(mailbox, action) =>
self.queue_for(&r).push(action), self.queue_for_mailbox(&mailbox).push(action),
Destination::ImmediateSelf(action) => Destination::ImmediateSelf(action) =>
self.immediate_self.push(action), self.immediate_self.push(action),
} }
} }
pub fn message<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> { pub fn message<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, m: M) {
if let Some(body) = r.rewrite(m.into()) { let r = Arc::clone(r);
let r = Arc::clone(r); self.queue_for(&r).push(Box::new(
self.queue_for(&r).push(Box::new( move |t| r.with_entity(|e| e.message(t, m))))
move |t| r.with_entity(|e| e.message(t, body))))
}
} }
pub fn message_immediate_self<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> { pub fn message_immediate_self<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, m: M) {
self.immediate_oid(r); self.immediate_oid(r);
if let Some(body) = r.rewrite(m.into()) { let r = Arc::clone(r);
let r = Arc::clone(r); self.immediate_self.push(Box::new(
self.immediate_self.push(Box::new( move |t| r.with_entity(|e| e.message(t, m))))
move |t| r.with_entity(|e| e.message(t, body))))
}
} }
pub fn sync(&mut self, r: &Arc<Ref>, peer: Arc<Ref>) { pub fn sync<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, peer: Arc<Ref<Synced>>) {
let r = Arc::clone(r); let r = Arc::clone(r);
self.queue_for(&r).push(Box::new( self.queue_for(&r).push(Box::new(
move |t| r.with_entity(|e| e.sync(t, peer)))) move |t| r.with_entity(|e| e.sync(t, peer))))
} }
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut PendingEventQueue { fn queue_for<M>(&mut self, r: &Arc<Ref<M>>) -> &mut PendingEventQueue {
&mut self.queues.entry(r.addr.mailbox.actor_id) self.queue_for_mailbox(&r.mailbox)
.or_insert((r.addr.mailbox.tx.clone(), Vec::new())).1 }
fn queue_for_mailbox(&mut self, mailbox: &Arc<Mailbox>) -> &mut PendingEventQueue {
&mut self.queues.entry(mailbox.actor_id)
.or_insert((mailbox.tx.clone(), Vec::new())).1
} }
fn deliver(&mut self) { fn deliver(&mut self) {
@ -389,26 +365,26 @@ fn send_actions(
impl std::fmt::Debug for Mailbox { impl std::fmt::Debug for Mailbox {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "#<Mailbox {}:{}>", self.actor_id, self.mailbox_id) write!(f, "#<Mailbox {}>", self.actor_id)
} }
} }
impl std::hash::Hash for Mailbox { impl std::hash::Hash for Mailbox {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.mailbox_id.hash(state) self.actor_id.hash(state)
} }
} }
impl Eq for Mailbox {} impl Eq for Mailbox {}
impl PartialEq for Mailbox { impl PartialEq for Mailbox {
fn eq(&self, other: &Mailbox) -> bool { fn eq(&self, other: &Mailbox) -> bool {
self.mailbox_id == other.mailbox_id self.actor_id == other.actor_id
} }
} }
impl Ord for Mailbox { impl Ord for Mailbox {
fn cmp(&self, other: &Mailbox) -> std::cmp::Ordering { fn cmp(&self, other: &Mailbox) -> std::cmp::Ordering {
return self.mailbox_id.cmp(&other.mailbox_id) return self.actor_id.cmp(&other.actor_id)
} }
} }
@ -418,33 +394,10 @@ impl PartialOrd for Mailbox {
} }
} }
impl Clone for Mailbox {
fn clone(&self) -> Self {
let Mailbox { actor_id, tx, mailbox_count, .. } = self;
let _old_refcount = mailbox_count.fetch_add(1, Ordering::SeqCst);
let new_mailbox = Mailbox {
actor_id: *actor_id,
mailbox_id: crate::next_mailbox_id(),
tx: tx.clone(),
mailbox_count: Arc::clone(mailbox_count),
};
// tracing::trace!(old_mailbox = debug(&self),
// new_mailbox = debug(&new_mailbox),
// new_mailbox_refcount = debug(_old_refcount + 1));
new_mailbox
}
}
impl Drop for Mailbox { impl Drop for Mailbox {
fn drop(&mut self) { fn drop(&mut self) {
let old_mailbox_refcount = self.mailbox_count.fetch_sub(1, Ordering::SeqCst); let _ = self.tx.send(SystemMessage::Release);
let new_mailbox_refcount = old_mailbox_refcount - 1; ()
// tracing::trace!(mailbox = debug(&self),
// new_mailbox_refcount);
if new_mailbox_refcount == 0 {
let _ = self.tx.send(SystemMessage::Release);
()
}
} }
} }
@ -457,29 +410,27 @@ impl Actor {
actor_id, actor_id,
tx, tx,
rx: Some(rx), rx: Some(rx),
mailbox_count: Arc::new(AtomicUsize::new(0)), mailbox: Weak::new(),
outbound_assertions: Map::new(), outbound_assertions: Map::new(),
next_task_id: 0, next_task_id: 0,
linked_tasks: Map::new(), linked_tasks: Map::new(),
exit_hooks: Vec::new(), exit_hooks: Vec::new(),
exit_status: None,
} }
} }
pub fn create_and_start<E: Entity + Send + std::marker::Sync + 'static>( pub fn create_and_start<M, E: Entity<M> + Send + Sync + 'static>(
name: tracing::Span, name: tracing::Span,
e: E, e: E,
) -> Arc<Ref> { ) -> Arc<Ref<M>> {
Self::create_and_start_rec(name, e, |_, _, _| ()) let r = Self::create_and_start_inert(name);
r.become_entity(e);
r
} }
pub fn create_and_start_rec<E: Entity + Send + std::marker::Sync + 'static, pub fn create_and_start_inert<M>(name: tracing::Span) -> Arc<Ref<M>> {
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>(
name: tracing::Span,
e: E,
f: F,
) -> Arc<Ref> {
let mut ac = Self::new(); let mut ac = Self::new();
let r = ac.create_rec(e, f); let r = ac.create_inert();
ac.start(name); ac.start(name);
r r
} }
@ -488,17 +439,18 @@ impl Actor {
self.actor_id self.actor_id
} }
fn mailbox(&mut self) -> Mailbox { fn mailbox(&mut self) -> Arc<Mailbox> {
let _old_refcount = self.mailbox_count.fetch_add(1, Ordering::SeqCst); match self.mailbox.upgrade() {
let new_mailbox = Mailbox { None => {
actor_id: self.actor_id, let new_mailbox = Arc::new(Mailbox {
mailbox_id: crate::next_mailbox_id(), actor_id: self.actor_id,
tx: self.tx.clone(), tx: self.tx.clone(),
mailbox_count: Arc::clone(&self.mailbox_count), });
}; self.mailbox = Arc::downgrade(&new_mailbox);
// tracing::trace!(new_mailbox = debug(&new_mailbox), new_mailbox
// new_mailbox_refcount = debug(_old_refcount + 1)); }
new_mailbox Some(m) => m
}
} }
pub fn shutdown(&mut self) { pub fn shutdown(&mut self) {
@ -506,25 +458,17 @@ impl Actor {
() ()
} }
pub fn create<E: Entity + Send + std::marker::Sync + 'static>(&mut self, e: E) -> Arc<Ref> { pub fn create<M, E: Entity<M> + Send + Sync + 'static>(&mut self, e: E) -> Arc<Ref<M>> {
self.create_rec(e, |_, _, _| ()) let r = self.create_inert();
r.become_entity(e);
r
} }
pub fn create_rec<E: Entity + Send + std::marker::Sync + 'static, pub fn create_inert<M>(&mut self) -> Arc<Ref<M>> {
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>( Arc::new(Ref {
&mut self, mailbox: self.mailbox(),
e: E, target: RwLock::new(None),
f: F, })
) -> Arc<Ref> {
let r = Arc::new(Ref {
addr: Arc::new(ObjectAddress {
mailbox: self.mailbox(),
target: RwLock::new(Box::new(e)),
}),
attenuation: Vec::new(),
});
f(self, r.addr.target.write().expect("unpoisoned").as_any().downcast_mut().unwrap(), &r);
r
} }
pub fn boot<F: 'static + Send + for<'a> FnOnce(&'a mut Activation) -> BoxFuture<'a, ActorResult>>( pub fn boot<F: 'static + Send + for<'a> FnOnce(&'a mut Activation) -> BoxFuture<'a, ActorResult>>(
@ -536,13 +480,12 @@ impl Actor {
tokio::spawn(async move { tokio::spawn(async move {
tracing::trace!("start"); tracing::trace!("start");
let result = self.run(boot).await; let result = self.run(boot).await;
self.exit_status = Some(Arc::new(result.clone()));
{ {
let mut t = Activation::new(&mut self, Debtor::new(crate::name!("shutdown"))); let mut t = Activation::new(&mut self, Debtor::new(crate::name!("shutdown")));
for r in std::mem::take(&mut t.actor.exit_hooks) { for action in std::mem::take(&mut t.actor.exit_hooks) {
if let Err(err) = r.with_entity(|e| e.exit_hook(&mut t, &result)) { if let Err(err) = action(&mut t) {
tracing::error!(err = debug(err), tracing::error!(err = debug(err), "error in exit hook");
r = debug(&r),
"error in exit hook");
} }
} }
} }
@ -583,8 +526,12 @@ impl Actor {
} }
} }
pub fn add_exit_hook(&mut self, r: &Arc<Ref>) { pub fn add_exit_hook<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>) {
self.exit_hooks.push(Arc::clone(r)) let r = Arc::clone(r);
self.exit_hooks.push(Box::new(move |t| {
let exit_status = Arc::clone(t.actor.exit_status.as_ref().expect("exited"));
r.with_entity(|e| e.exit_hook(t, &exit_status))
}))
} }
async fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> { async fn handle(&mut self, m: SystemMessage) -> Result<bool, Error> {
@ -673,25 +620,89 @@ impl Drop for Actor {
} }
#[must_use] #[must_use]
pub fn external_event(r: &Arc<Ref>, debtor: &Arc<Debtor>, action: Action) -> ActorResult { pub fn external_event(mailbox: &Arc<Mailbox>, debtor: &Arc<Debtor>, action: Action) -> ActorResult {
send_actions(&r.addr.mailbox.tx, debtor, vec![action]) send_actions(&mailbox.tx, debtor, vec![action])
} }
#[must_use] #[must_use]
pub fn external_events(r: &Arc<Ref>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult { pub fn external_events(mailbox: &Arc<Mailbox>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult {
send_actions(&r.addr.mailbox.tx, debtor, events) send_actions(&mailbox.tx, debtor, events)
} }
impl Ref { impl<M> Ref<M> {
pub fn with_entity<R, F: FnOnce(&mut dyn Entity) -> R>(&self, f: F) -> R { pub fn become_entity<E: 'static + Entity<M>>(&self, e: E) {
f(&mut **self.addr.target.write().expect("unpoisoned")) let mut g = self.target.write().expect("unpoisoned");
if g.is_some() {
panic!("Double initialization of Ref");
}
*g = Some(Box::new(e));
}
pub fn with_entity<R, F: FnOnce(&mut dyn Entity<M>) -> R>(&self, f: F) -> R {
let mut g = self.target.write().expect("unpoisoned");
f(g.as_mut().expect("initialized").as_mut())
}
}
impl<M> Ref<M> {
pub fn oid(&self) -> usize {
std::ptr::addr_of!(*self) as usize
}
}
impl<M> PartialEq for Ref<M> {
fn eq(&self, other: &Self) -> bool {
self.oid() == other.oid()
}
}
impl<M> Eq for Ref<M> {}
impl<M> std::hash::Hash for Ref<M> {
fn hash<H>(&self, hash: &mut H) where H: std::hash::Hasher {
self.oid().hash(hash)
}
}
impl<M> PartialOrd for Ref<M> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<M> Ord for Ref<M> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.oid().cmp(&other.oid())
}
}
impl<M> std::fmt::Debug for Ref<M> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "⌜{}:{:016x}⌝", self.mailbox.actor_id, self.oid())
}
}
impl Cap {
pub fn guard<M: 'static + Send + Sync>(underlying: &Arc<Ref<M>>) -> Arc<Self>
where
for<'a> &'a M: Into<_Any>,
for<'a> M: TryFrom<&'a _Any>,
{
Self::new(&Arc::new(Ref {
mailbox: Arc::clone(&underlying.mailbox),
target: RwLock::new(Some(Box::new(Guard { underlying: underlying.clone() }))),
}))
}
pub fn new(underlying: &Arc<Ref<_Any>>) -> Arc<Self> {
Arc::new(Cap {
underlying: Arc::clone(underlying),
attenuation: Vec::new(),
})
} }
pub fn attenuate(&self, attenuation: &sturdy::Attenuation) -> Result<Arc<Self>, CaveatError> { pub fn attenuate(&self, attenuation: &sturdy::Attenuation) -> Result<Arc<Self>, CaveatError> {
let mut r = Ref { let mut r = Cap { attenuation: self.attenuation.clone(), .. self.clone() };
addr: Arc::clone(&self.addr),
attenuation: self.attenuation.clone(),
};
r.attenuation.extend(attenuation.check()?); r.attenuation.extend(attenuation.check()?);
Ok(Arc::new(r)) Ok(Arc::new(r))
} }
@ -705,33 +716,77 @@ impl Ref {
} }
Some(a) Some(a)
} }
}
impl std::fmt::Debug for Ref { pub fn assert<M: Into<_Any>>(&self, t: &mut Activation, m: M) -> Option<Handle> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { self.rewrite(m.into()).map(|m| t.assert(&self.underlying, m))
if self.attenuation.is_empty() { }
write!(f, "⌜{}:{:016x}⌝", self.addr.mailbox.actor_id, self.addr.oid())
} else { pub fn message<M: Into<_Any>>(&self, t: &mut Activation, m: M) {
write!(f, "⌜{}:{:016x}\\{:?}⌝", self.addr.mailbox.actor_id, self.addr.oid(), self.attenuation) if let Some(m) = self.rewrite(m.into()) {
t.message(&self.underlying, m)
} }
} }
} }
impl Domain for Ref {} impl std::fmt::Debug for Cap {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
impl std::convert::TryFrom<&IOValue> for Ref { if self.attenuation.is_empty() {
type Error = preserves_schema::support::ParseError; self.underlying.fmt(f)
fn try_from(_v: &IOValue) -> Result<Self, Self::Error> { } else {
panic!("Attempted to serialize Ref via IOValue"); write!(f, "⌜{}:{:016x}\\{:?}⌝",
self.underlying.mailbox.actor_id,
self.underlying.oid(),
self.attenuation)
}
} }
} }
impl std::convert::From<&Ref> for IOValue { impl Domain for Cap {}
fn from(_v: &Ref) -> IOValue {
impl std::convert::TryFrom<&IOValue> for Cap {
type Error = preserves_schema::support::ParseError;
fn try_from(_v: &IOValue) -> Result<Self, Self::Error> {
panic!("Attempted to serialize Cap via IOValue");
}
}
impl std::convert::From<&Cap> for IOValue {
fn from(_v: &Cap) -> IOValue {
panic!("Attempted to deserialize Ref via IOValue"); panic!("Attempted to deserialize Ref via IOValue");
} }
} }
impl<M> Entity<_Any> for Guard<M>
where
for<'a> &'a M: Into<_Any>,
for<'a> M: TryFrom<&'a _Any>,
{
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
match M::try_from(&a) {
Ok(a) => self.underlying.with_entity(|e| e.assert(t, a, h)),
Err(_) => Ok(()),
}
}
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
self.underlying.with_entity(|e| e.retract(t, h))
}
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
match M::try_from(&m) {
Ok(m) => self.underlying.with_entity(|e| e.message(t, m)),
Err(_) => Ok(()),
}
}
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
self.underlying.with_entity(|e| e.sync(t, peer))
}
fn turn_end(&mut self, t: &mut Activation) -> ActorResult {
self.underlying.with_entity(|e| e.turn_end(t))
}
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
self.underlying.with_entity(|e| e.exit_hook(t, exit_status))
}
}
#[macro_export] #[macro_export]
macro_rules! name { macro_rules! name {
() => {tracing::info_span!(actor_id = tracing::field::Empty, () => {tracing::info_span!(actor_id = tracing::field::Empty,

View File

@ -5,8 +5,6 @@ use preserves::value::Map;
use preserves::value::NestedValue; use preserves::value::NestedValue;
use preserves::value::Value; use preserves::value::Value;
use std::any::Any;
use std::convert::TryFrom;
use std::future::ready; use std::future::ready;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::sync::Arc; use std::sync::Arc;
@ -21,6 +19,7 @@ use syndicate::error::error;
use syndicate::config; use syndicate::config;
use syndicate::relay; use syndicate::relay;
use syndicate::schemas::internal_protocol::_Any; use syndicate::schemas::internal_protocol::_Any;
use syndicate::schemas::gatekeeper;
use syndicate::sturdy; use syndicate::sturdy;
use tokio::net::TcpListener; use tokio::net::TcpListener;
@ -72,10 +71,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing::trace!("startup"); tracing::trace!("startup");
let ds = Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new()); let ds = Cap::new(&Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new()));
let gateway = Actor::create_and_start( let gateway = Cap::guard(&Actor::create_and_start(
syndicate::name!("gateway"), syndicate::name!("gateway"),
syndicate::entity(Arc::clone(&ds)).on_asserted(handle_resolve)); syndicate::entity(Arc::clone(&ds)).on_asserted(handle_resolve)));
{ {
let ds = Arc::clone(&ds); let ds = Arc::clone(&ds);
Actor::new().boot(syndicate::name!("rootcap"), |t| Box::pin(async move { Actor::new().boot(syndicate::name!("rootcap"), |t| Box::pin(async move {
@ -84,7 +83,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sr = sturdy::SturdyRef::mint(_Any::new("syndicate"), &key); let sr = sturdy::SturdyRef::mint(_Any::new("syndicate"), &key);
tracing::info!(rootcap = debug(&_Any::from(&sr))); tracing::info!(rootcap = debug(&_Any::from(&sr)));
tracing::info!(rootcap = display(sr.to_hex())); tracing::info!(rootcap = display(sr.to_hex()));
t.assert(&ds, &gatekeeper::Bind { oid: sr.oid.clone(), key, target: ds.clone() }); ds.assert(t, &gatekeeper::Bind { oid: sr.oid.clone(), key, target: ds.clone() });
Ok(()) Ok(())
})); }));
} }
@ -131,7 +130,7 @@ fn extract_binary_packets(
async fn run_connection( async fn run_connection(
t: &mut Activation<'_>, t: &mut Activation<'_>,
stream: TcpStream, stream: TcpStream,
gateway: Arc<Ref>, gateway: Arc<Cap>,
addr: std::net::SocketAddr, addr: std::net::SocketAddr,
config: Arc<config::ServerConfig>, config: Arc<config::ServerConfig>,
) -> ActorResult { ) -> ActorResult {
@ -158,11 +157,8 @@ async fn run_connection(
_ => unreachable!() _ => unreachable!()
}; };
struct ExitListener; struct ExitListener;
impl Entity for ExitListener { impl Entity<()> for ExitListener {
fn as_any(&mut self) -> &mut dyn Any { fn exit_hook(&mut self, _t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
self
}
fn exit_hook(&mut self, _t: &mut Activation, exit_status: &ActorResult) -> ActorResult {
tracing::info!(exit_status = debug(exit_status), "disconnect"); tracing::info!(exit_status = debug(exit_status), "disconnect");
Ok(()) Ok(())
} }
@ -174,7 +170,7 @@ async fn run_connection(
} }
async fn run_listener( async fn run_listener(
gateway: Arc<Ref>, gateway: Arc<Cap>,
port: u16, port: u16,
config: Arc<config::ServerConfig>, config: Arc<config::ServerConfig>,
) -> ActorResult { ) -> ActorResult {
@ -193,59 +189,65 @@ async fn run_listener(
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
fn handle_resolve(ds: &mut Arc<Ref>, t: &mut Activation, a: _Any) -> DuringResult<Arc<Ref>> { fn handle_resolve(
ds: &mut Arc<Cap>,
t: &mut Activation,
a: gatekeeper::Resolve,
) -> DuringResult<Arc<Cap>> {
use syndicate::schemas::dataspace; use syndicate::schemas::dataspace;
use syndicate::schemas::dataspace_patterns as p; use syndicate::schemas::dataspace_patterns as p;
use syndicate::schemas::gatekeeper;
match gatekeeper::Resolve::try_from(&a) { let gatekeeper::Resolve { sturdyref, observer } = a;
Err(_) => Ok(None), let queried_oid = sturdyref.oid.clone();
Ok(gatekeeper::Resolve { sturdyref, observer }) => { let handler = syndicate::entity(observer)
let queried_oid = sturdyref.oid.clone(); .on_asserted(move |observer, t, a: _Any| {
let handler = syndicate::entity(observer) let bindings = a.value().to_sequence()?;
.on_asserted(move |observer, t, a| { let key = bindings[0].value().to_bytestring()?;
let bindings = a.value().to_sequence()?; let unattenuated_target = bindings[1].value().to_embedded()?;
let key = bindings[0].value().to_bytestring()?; match sturdyref.validate_and_attenuate(key, unattenuated_target) {
let unattenuated_target = bindings[1].value().to_embedded()?; Err(e) => {
match sturdyref.validate_and_attenuate(key, unattenuated_target) { tracing::warn!(sturdyref = debug(&_Any::from(&sturdyref)),
Err(e) => { "sturdyref failed validation: {}", e);
tracing::warn!(sturdyref = debug(&_Any::from(&sturdyref)), Ok(None)
"sturdyref failed validation: {}", e); },
Ok(None) Ok(target) => {
}, tracing::trace!(sturdyref = debug(&_Any::from(&sturdyref)),
Ok(target) => { target = debug(&target),
tracing::trace!(sturdyref = debug(&_Any::from(&sturdyref)), "sturdyref resolved");
target = debug(&target), if let Some(h) = observer.assert(t, _Any::domain(target)) {
"sturdyref resolved"); Ok(Some(Box::new(move |_observer, t| Ok(t.retract(h)))))
let h = t.assert(observer, _Any::domain(target)); } else {
Ok(Some(Box::new(move |_observer, t| Ok(t.retract(h))))) Ok(None)
}
} }
}) }
.create(t.actor); }
let oh = t.assert(ds, &dataspace::Observe { })
// TODO: codegen plugin to generate pattern constructors .create_cap(t.actor);
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { if let Some(oh) = ds.assert(t, &dataspace::Observe {
ctor: Box::new(p::CRec { // TODO: codegen plugin to generate pattern constructors
label: Value::symbol("bind").wrap(), pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
arity: 3.into(), ctor: Box::new(p::CRec {
}), label: Value::symbol("bind").wrap(),
members: Map::from_iter(vec![ arity: 3.into(),
(0.into(), p::Pattern::DLit(Box::new(p::DLit { }),
value: queried_oid, members: Map::from_iter(vec![
}))), (0.into(), p::Pattern::DLit(Box::new(p::DLit {
(1.into(), p::Pattern::DBind(Box::new(p::DBind { value: queried_oid,
name: "key".to_owned(), }))),
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)), (1.into(), p::Pattern::DBind(Box::new(p::DBind {
}))), name: "key".to_owned(),
(2.into(), p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
name: "target".to_owned(), }))),
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)), (2.into(), p::Pattern::DBind(Box::new(p::DBind {
}))), name: "target".to_owned(),
].into_iter()) pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
})), }))),
observer: handler, ].into_iter())
}); })),
Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh))))) observer: handler,
} }) {
Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh)))))
} else {
Ok(None)
} }
} }

View File

@ -5,7 +5,6 @@ use super::schemas::dataspace::_Any;
use preserves::value::Map; use preserves::value::Map;
use std::any::Any;
use std::convert::TryFrom; use std::convert::TryFrom;
#[derive(Debug)] #[derive(Debug)]
@ -68,10 +67,7 @@ impl Dataspace {
} }
} }
impl Entity for Dataspace { impl Entity<_Any> for Dataspace {
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult { fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
// tracing::trace!(assertion = debug(&a), handle = debug(&h), "assert"); // tracing::trace!(assertion = debug(&a), handle = debug(&h), "assert");

View File

@ -3,26 +3,25 @@ use crate::error::Error;
use preserves::value::Map; use preserves::value::Map;
use std::any::Any;
use std::sync::Arc; use std::sync::Arc;
use std::marker::PhantomData;
pub type DuringRetractionHandler<T> = Box<dyn Send + Sync + FnOnce(&mut T, &mut Activation) -> ActorResult>;
pub struct During<T>(Map<Handle, DuringRetractionHandler<T>>); pub struct During<T>(Map<Handle, DuringRetractionHandler<T>>);
pub type DuringRetractionHandler<T> = Box<dyn Send + Sync + FnOnce(&mut T, &mut Activation) -> ActorResult>;
pub type DuringResult<E> = Result<Option<DuringRetractionHandler<E>>, Error>;
pub type DuringResult<E> = pub struct DuringEntity<M, E, Fa, Fm>
Result<Option<Box<dyn 'static + Send + Sync + FnOnce(&mut E, &mut Activation) -> ActorResult>>,
Error>;
pub struct DuringEntity<E, Fa, Fm>
where where
M: 'static + Send + Sync,
E: 'static + Send + Sync, E: 'static + Send + Sync,
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>, Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult, Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
{ {
state: E, state: E,
assertion_handler: Option<Fa>, assertion_handler: Option<Fa>,
message_handler: Option<Fm>, message_handler: Option<Fm>,
during: During<E>, during: During<E>,
phantom: PhantomData<M>,
} }
impl<T> During<T> { impl<T> During<T> {
@ -44,22 +43,24 @@ impl<T> During<T> {
} }
} }
pub fn entity<E>( pub fn entity<M: 'static + Send + Sync, E>(
state: E state: E
) -> DuringEntity<E, ) -> DuringEntity<M,
fn (&mut E, &mut Activation, _Any) -> DuringResult<E>, E,
fn (&mut E, &mut Activation, _Any) -> ActorResult> fn (&mut E, &mut Activation, M) -> DuringResult<E>,
fn (&mut E, &mut Activation, M) -> ActorResult>
where where
E: 'static + Send + Sync, E: 'static + Send + Sync,
{ {
DuringEntity::new(state, None, None) DuringEntity::new(state, None, None)
} }
impl<E, Fa, Fm> DuringEntity<E, Fa, Fm> impl<M, E, Fa, Fm> DuringEntity<M, E, Fa, Fm>
where where
M: 'static + Send + Sync,
E: 'static + Send + Sync, E: 'static + Send + Sync,
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>, Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult, Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
{ {
pub fn new(state: E, assertion_handler: Option<Fa>, message_handler: Option<Fm>) -> Self { pub fn new(state: E, assertion_handler: Option<Fa>, message_handler: Option<Fm>) -> Self {
DuringEntity { DuringEntity {
@ -67,56 +68,61 @@ where
assertion_handler, assertion_handler,
message_handler, message_handler,
during: During::new(), during: During::new(),
phantom: PhantomData,
} }
} }
pub fn on_asserted<Fa1>(self, assertion_handler: Fa1) -> DuringEntity<E, Fa1, Fm> pub fn on_asserted<Fa1>(self, assertion_handler: Fa1) -> DuringEntity<M, E, Fa1, Fm>
where where
Fa1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>, Fa1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
{ {
DuringEntity { DuringEntity {
state: self.state, state: self.state,
assertion_handler: Some(assertion_handler), assertion_handler: Some(assertion_handler),
message_handler: self.message_handler, message_handler: self.message_handler,
during: self.during, during: self.during,
phantom: PhantomData,
} }
} }
pub fn on_message<Fm1>(self, message_handler: Fm1) -> DuringEntity<E, Fa, Fm1> pub fn on_message<Fm1>(self, message_handler: Fm1) -> DuringEntity<M, E, Fa, Fm1>
where where
Fm1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult, Fm1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
{ {
DuringEntity { DuringEntity {
state: self.state, state: self.state,
assertion_handler: self.assertion_handler, assertion_handler: self.assertion_handler,
message_handler: Some(message_handler), message_handler: Some(message_handler),
during: self.during, during: self.during,
phantom: PhantomData,
} }
} }
pub fn create(self, ac: &mut Actor) -> Arc<Ref> { pub fn create(self, ac: &mut Actor) -> Arc<Ref<M>> {
ac.create(self) ac.create(self)
} }
pub fn create_rec<F>(self, ac: &mut Actor, f: F) -> Arc<Ref>
where
F: FnOnce(&mut Actor, &mut E, &Arc<Ref>) -> ()
{
ac.create_rec(self, |ac, e, e_ref| f(ac, &mut e.state, e_ref))
}
} }
impl<E, Fa, Fm> Entity for DuringEntity<E, Fa, Fm> impl<E, Fa, Fm> DuringEntity<_Any, E, Fa, Fm>
where where
E: 'static + Send + Sync, E: 'static + Send + Sync,
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>, Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>,
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult, Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult,
{ {
fn as_any(&mut self) -> &mut dyn Any { pub fn create_cap(self, ac: &mut Actor) -> Arc<Cap>
self {
Cap::new(&self.create(ac))
} }
}
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult { impl<M, E, Fa, Fm> Entity<M> for DuringEntity<M, E, Fa, Fm>
where
M: Send + Sync,
E: 'static + Send + Sync,
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
{
fn assert(&mut self, t: &mut Activation, a: M, h: Handle) -> ActorResult {
match &mut self.assertion_handler { match &mut self.assertion_handler {
Some(handler) => match handler(&mut self.state, t, a)? { Some(handler) => match handler(&mut self.state, t, a)? {
Some(f) => self.during.await_retraction(h, f), Some(f) => self.during.await_retraction(h, f),
@ -130,7 +136,7 @@ where
self.during.retract(h)(&mut self.state, t) self.during.retract(h)(&mut self.state, t)
} }
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult { fn message(&mut self, t: &mut Activation, m: M) -> ActorResult {
match &mut self.message_handler { match &mut self.message_handler {
Some(handler) => handler(&mut self.state, t, m), Some(handler) => handler(&mut self.state, t, m),
None => Ok(()), None => Ok(()),

View File

@ -16,7 +16,7 @@ impl std::fmt::Display for Error {
pub fn error<Detail>(message: &str, detail: Detail) -> Error where _Any: From<Detail> { pub fn error<Detail>(message: &str, detail: Detail) -> Error where _Any: From<Detail> {
Error { Error {
message: message.to_owned(), message: message.to_owned(),
detail: detail.into(), detail: _Any::from(detail),
} }
} }

View File

@ -37,8 +37,3 @@ static NEXT_HANDLE: AtomicU64 = AtomicU64::new(3);
pub fn next_handle() -> Handle { pub fn next_handle() -> Handle {
NEXT_HANDLE.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed) NEXT_HANDLE.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed)
} }
static NEXT_MAILBOX_ID: AtomicU64 = AtomicU64::new(4);
pub fn next_mailbox_id() -> u64 {
NEXT_MAILBOX_ID.fetch_add(BUMP_AMOUNT.into(), Ordering::Relaxed)
}

View File

@ -8,7 +8,6 @@ use crate::error::error;
use crate::schemas::gatekeeper; use crate::schemas::gatekeeper;
use crate::schemas::internal_protocol as P; use crate::schemas::internal_protocol as P;
use crate::schemas::sturdy; use crate::schemas::sturdy;
use crate::schemas::tunnel_relay;
use futures::Sink; use futures::Sink;
use futures::SinkExt; use futures::SinkExt;
@ -34,7 +33,6 @@ use preserves::value::signed_integer::SignedInteger;
use preserves_schema::support::Deserialize; use preserves_schema::support::Deserialize;
use preserves_schema::support::ParseError; use preserves_schema::support::ParseError;
use std::any::Any;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::io; use std::io;
use std::pin::Pin; use std::pin::Pin;
@ -49,15 +47,28 @@ use tokio::io::AsyncWriteExt;
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver}; use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
enum RelayInput {
Eof,
Packet(Vec<u8>),
Segment(Vec<u8>),
}
enum RelayProtocol {
Input(RelayInput),
Output(sturdy::Oid, P::Event),
SyncGc(Arc<Cap>),
Flush,
}
struct WireSymbol { struct WireSymbol {
oid: sturdy::Oid, oid: sturdy::Oid,
obj: Arc<Ref>, obj: Arc<Cap>,
ref_count: AtomicUsize, ref_count: AtomicUsize,
} }
struct Membrane { struct Membrane {
oid_map: Map<sturdy::Oid, Arc<WireSymbol>>, oid_map: Map<sturdy::Oid, Arc<WireSymbol>>,
ref_map: Map<Arc<Ref>, Arc<WireSymbol>>, ref_map: Map<Arc<Cap>, Arc<WireSymbol>>,
} }
struct Membranes { struct Membranes {
@ -76,10 +87,12 @@ pub enum Output {
Bytes(Pin<Box<dyn AsyncWrite + Send>>), Bytes(Pin<Box<dyn AsyncWrite + Send>>),
} }
type TunnelRelayRef = Arc<Ref<RelayProtocol>>;
// There are other kinds of relay. This one has exactly two participants connected to each other. // There are other kinds of relay. This one has exactly two participants connected to each other.
pub struct TunnelRelay pub struct TunnelRelay
{ {
self_ref: Arc<Ref>, self_ref: TunnelRelayRef,
input_buffer: BytesMut, input_buffer: BytesMut,
inbound_assertions: Map</* remote */ P::Handle, (/* local */ Handle, Vec<Arc<WireSymbol>>)>, inbound_assertions: Map</* remote */ P::Handle, (/* local */ Handle, Vec<Arc<WireSymbol>>)>,
outbound_assertions: Map<P::Handle, Vec<Arc<WireSymbol>>>, outbound_assertions: Map<P::Handle, Vec<Arc<WireSymbol>>>,
@ -89,7 +102,7 @@ pub struct TunnelRelay
} }
struct RelayEntity { struct RelayEntity {
relay_ref: Arc<Ref>, relay_ref: TunnelRelayRef,
oid: sturdy::Oid, oid: sturdy::Oid,
} }
@ -113,7 +126,7 @@ impl Membrane {
} }
} }
fn insert(&mut self, oid: sturdy::Oid, obj: Arc<Ref>) -> Arc<WireSymbol> { fn insert(&mut self, oid: sturdy::Oid, obj: Arc<Cap>) -> Arc<WireSymbol> {
let ws = Arc::new(WireSymbol { let ws = Arc::new(WireSymbol {
oid: oid.clone(), oid: oid.clone(),
obj: Arc::clone(&obj), obj: Arc::clone(&obj),
@ -124,7 +137,7 @@ impl Membrane {
ws ws
} }
fn acquire(&mut self, r: &Arc<Ref>) -> Arc<WireSymbol> { fn acquire(&mut self, r: &Arc<Cap>) -> Arc<WireSymbol> {
let ws = self.ref_map.get(r).expect("WireSymbol must be present at acquire() time"); let ws = self.ref_map.get(r).expect("WireSymbol must be present at acquire() time");
ws.acquire(); ws.acquire();
Arc::clone(ws) Arc::clone(ws)
@ -149,18 +162,18 @@ pub fn connect_stream<I, O, E, F>(
I: 'static + Send + AsyncRead, I: 'static + Send + AsyncRead,
O: 'static + Send + AsyncWrite, O: 'static + Send + AsyncWrite,
E: 'static + Send + std::marker::Sync, E: 'static + Send + std::marker::Sync,
F: 'static + Send + std::marker::Sync + FnMut(&mut E, &mut Activation, Arc<Ref>) -> during::DuringResult<E> F: 'static + Send + std::marker::Sync + FnMut(&mut E, &mut Activation, Arc<Cap>) -> during::DuringResult<E>
{ {
let i = Input::Bytes(Box::pin(i)); let i = Input::Bytes(Box::pin(i));
let o = Output::Bytes(Box::pin(o)); let o = Output::Bytes(Box::pin(o));
let gatekeeper = TunnelRelay::run(t, i, o, None, Some(sturdy::Oid(0.into()))).unwrap(); let gatekeeper = TunnelRelay::run(t, i, o, None, Some(sturdy::Oid(0.into()))).unwrap();
let main_entity = t.actor.create(during::entity(initial_state).on_asserted(move |state, t, a| { let main_entity = t.actor.create(during::entity(initial_state).on_asserted(move |state, t, a: _Any| {
let denotation = a.value().to_embedded()?; let denotation = a.value().to_embedded()?;
f(state, t, Arc::clone(denotation)) f(state, t, Arc::clone(denotation))
})); }));
t.assert(&gatekeeper, &gatekeeper::Resolve { gatekeeper.assert(t, &gatekeeper::Resolve {
sturdyref, sturdyref,
observer: main_entity, observer: Cap::new(&main_entity),
}); });
} }
@ -169,12 +182,12 @@ impl TunnelRelay {
t: &mut Activation, t: &mut Activation,
i: Input, i: Input,
o: Output, o: Output,
initial_ref: Option<Arc<Ref>>, initial_ref: Option<Arc<Cap>>,
initial_oid: Option<sturdy::Oid>, initial_oid: Option<sturdy::Oid>,
) -> Option<Arc<Ref>> { ) -> Option<Arc<Cap>> {
let (output_tx, output_rx) = unbounded_channel(); let (output_tx, output_rx) = unbounded_channel();
let mut tr = TunnelRelay { let mut tr = TunnelRelay {
self_ref: Arc::clone(&*INERT_REF), /* placeholder */ self_ref: t.actor.create_inert(),
input_buffer: BytesMut::with_capacity(1024), input_buffer: BytesMut::with_capacity(1024),
output: output_tx, output: output_tx,
inbound_assertions: Map::new(), inbound_assertions: Map::new(),
@ -189,13 +202,10 @@ impl TunnelRelay {
if let Some(ir) = initial_ref { if let Some(ir) = initial_ref {
tr.membranes.export_ref(ir, true); tr.membranes.export_ref(ir, true);
} }
let mut result = None; let result = initial_oid.map(
let tr_ref = t.actor.create_rec(tr, |ac, tr, tr_ref| { |io| Arc::clone(&tr.membranes.import_oid(t.actor, &tr.self_ref, io).obj));
tr.self_ref = Arc::clone(tr_ref); let tr_ref = Arc::clone(&tr.self_ref);
if let Some(io) = initial_oid { tr_ref.become_entity(tr);
result = Some(Arc::clone(&tr.membranes.import_oid(ac, tr_ref, io).obj));
}
});
t.actor.add_exit_hook(&tr_ref); t.actor.add_exit_hook(&tr_ref);
t.actor.linked_task(crate::name!("writer"), output_loop(o, output_rx)); t.actor.linked_task(crate::name!("writer"), output_loop(o, output_rx));
t.actor.linked_task(crate::name!("reader"), input_loop(i, tr_ref)); t.actor.linked_task(crate::name!("reader"), input_loop(i, tr_ref));
@ -228,9 +238,10 @@ impl TunnelRelay {
a.foreach_embedded::<_, Error>(&mut |r| { a.foreach_embedded::<_, Error>(&mut |r| {
Ok(imported.push(imported_membrane.acquire(r))) Ok(imported.push(imported_membrane.acquire(r)))
})?; })?;
let local_handle = t.assert(target, a); if let Some(local_handle) = target.assert(t, a) {
if let Some(_) = self.inbound_assertions.insert(remote_handle, (local_handle, imported)) { if let Some(_) = self.inbound_assertions.insert(remote_handle, (local_handle, imported)) {
return Err(error("Assertion with duplicate handle", _Any::new(false))); return Err(error("Assertion with duplicate handle", _Any::new(false)));
}
} }
} }
P::Event::Retract(b) => { P::Event::Retract(b) => {
@ -254,26 +265,20 @@ impl TunnelRelay {
_ => Ok(()) _ => Ok(())
} }
})?; })?;
t.message(target, a); target.message(t, a);
} }
P::Event::Sync(b) => { P::Event::Sync(b) => {
let P::Sync { peer } = *b; let P::Sync { peer } = *b;
self.membranes.imported.acquire(&peer); self.membranes.imported.acquire(&peer);
struct SyncPeer { struct SyncPeer {
tr: Arc<Ref>, tr: TunnelRelayRef,
peer: Arc<Ref>, peer: Arc<Cap>,
} }
impl Entity for SyncPeer { impl Entity<Synced> for SyncPeer {
fn as_any(&mut self) -> &mut dyn Any { fn message(&mut self, t: &mut Activation, _a: Synced) -> ActorResult {
self self.peer.message(t, _Any::new(true));
} t.message(&self.tr, RelayProtocol::SyncGc(
fn message(&mut self, t: &mut Activation, a: _Any) -> ActorResult { Arc::clone(&self.peer)));
if let Some(true) = a.value().as_boolean() {
t.message(&self.peer, _Any::new(true));
t.message(&self.tr, &tunnel_relay::SyncGc {
peer: Arc::clone(&self.peer)
});
}
Ok(()) Ok(())
} }
} }
@ -281,7 +286,7 @@ impl TunnelRelay {
tr: Arc::clone(&self.self_ref), tr: Arc::clone(&self.self_ref),
peer: Arc::clone(&peer), peer: Arc::clone(&peer),
}); });
t.sync(&peer, k); t.sync(&peer.underlying, k);
} }
} }
} }
@ -336,7 +341,7 @@ impl TunnelRelay {
} }
impl Membranes { impl Membranes {
fn export_ref(&mut self, obj: Arc<Ref>, and_acquire: bool) -> Arc<WireSymbol> { fn export_ref(&mut self, obj: Arc<Cap>, and_acquire: bool) -> Arc<WireSymbol> {
let ws = match self.exported.ref_map.get(&obj) { let ws = match self.exported.ref_map.get(&obj) {
None => { None => {
let oid = sturdy::Oid(SignedInteger::from(self.next_export_oid as u128)); let oid = sturdy::Oid(SignedInteger::from(self.next_export_oid as u128));
@ -354,17 +359,17 @@ impl Membranes {
fn import_oid( fn import_oid(
&mut self, &mut self,
ac: &mut Actor, ac: &mut Actor,
relay_ref: &Arc<Ref>, relay_ref: &TunnelRelayRef,
oid: sturdy::Oid, oid: sturdy::Oid,
) -> Arc<WireSymbol> { ) -> Arc<WireSymbol> {
let obj = ac.create(RelayEntity { relay_ref: Arc::clone(relay_ref), oid: oid.clone() }); let obj = ac.create(RelayEntity { relay_ref: Arc::clone(relay_ref), oid: oid.clone() });
self.imported.insert(oid, obj) self.imported.insert(oid, Cap::new(&obj))
} }
fn decode_embedded<'de, 'src, S: BinarySource<'de>>( fn decode_embedded<'de, 'src, S: BinarySource<'de>>(
&mut self, &mut self,
t: &mut Activation, t: &mut Activation,
relay_ref: &Arc<Ref>, relay_ref: &TunnelRelayRef,
src: &'src mut S, src: &'src mut S,
_read_annotations: bool, _read_annotations: bool,
) -> io::Result<P::_Ptr> { ) -> io::Result<P::_Ptr> {
@ -392,7 +397,7 @@ impl Membranes {
})?) })?)
} }
} }
None => Ok(Arc::clone(&*INERT_REF)), None => Ok(Cap::new(&t.actor.create_inert())),
} }
} }
} }
@ -400,7 +405,7 @@ impl Membranes {
} }
struct ActivatedMembranes<'a, 'activation, 'm>(&'a mut Activation<'activation>, struct ActivatedMembranes<'a, 'activation, 'm>(&'a mut Activation<'activation>,
&'m Arc<Ref>, &'m TunnelRelayRef,
&'m mut Membranes); &'m mut Membranes);
impl<'a, 'activation, 'm> DomainDecode<P::_Ptr> for ActivatedMembranes<'a, 'activation, 'm> { impl<'a, 'activation, 'm> DomainDecode<P::_Ptr> for ActivatedMembranes<'a, 'activation, 'm> {
@ -448,17 +453,20 @@ impl DomainEncode<P::_Ptr> for Membranes {
} }
} }
pub async fn input_loop( async fn input_loop(
i: Input, i: Input,
relay: Arc<Ref>, relay: TunnelRelayRef,
) -> ActorResult { ) -> ActorResult {
#[must_use] #[must_use]
async fn s<M: Into<_Any>>(relay: &Arc<Ref>, debtor: &Arc<Debtor>, m: M) -> ActorResult { async fn s(
relay: &TunnelRelayRef,
debtor: &Arc<Debtor>,
m: RelayInput,
) -> ActorResult {
debtor.ensure_clear_funds().await; debtor.ensure_clear_funds().await;
let m = m.into();
let relay = Arc::clone(relay); let relay = Arc::clone(relay);
external_event(&Arc::clone(&relay), debtor, Box::new( external_event(&Arc::clone(&relay.mailbox), debtor, Box::new(
move |t| relay.with_entity(|e| e.message(t, m)))) move |t| relay.with_entity(|e| e.message(t, RelayProtocol::Input(m)))))
} }
let debtor = Debtor::new(crate::name!("input-loop")); let debtor = Debtor::new(crate::name!("input-loop"));
@ -468,11 +476,11 @@ pub async fn input_loop(
loop { loop {
match src.next().await { match src.next().await {
None => { None => {
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?; s(&relay, &debtor, RelayInput::Eof).await?;
return Ok(()); return Ok(());
} }
Some(bs) => { Some(bs) => {
s(&relay, &debtor, &tunnel_relay::Input::Packet { bs: bs? }).await?; s(&relay, &debtor, RelayInput::Packet(bs?)).await?;
} }
} }
} }
@ -486,7 +494,7 @@ pub async fn input_loop(
Ok(n) => n, Ok(n) => n,
Err(e) => Err(e) =>
if e.kind() == io::ErrorKind::ConnectionReset { if e.kind() == io::ErrorKind::ConnectionReset {
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?; s(&relay, &debtor, RelayInput::Eof).await?;
return Ok(()); return Ok(());
} else { } else {
return Err(e)?; return Err(e)?;
@ -494,14 +502,14 @@ pub async fn input_loop(
}; };
match n { match n {
0 => { 0 => {
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?; s(&relay, &debtor, RelayInput::Eof).await?;
return Ok(()); return Ok(());
} }
_ => { _ => {
while buf.has_remaining() { while buf.has_remaining() {
let bs = buf.chunk(); let bs = buf.chunk();
let n = bs.len(); let n = bs.len();
s(&relay, &debtor, &tunnel_relay::Input::Segment { bs: bs.to_vec() }).await?; s(&relay, &debtor, RelayInput::Segment(bs.to_vec())).await?;
buf.advance(n); buf.advance(n);
} }
} }
@ -511,7 +519,7 @@ pub async fn input_loop(
} }
} }
pub async fn output_loop( async fn output_loop(
mut o: Output, mut o: Output,
mut output_rx: UnboundedReceiver<LoanedItem<Vec<u8>>>, mut output_rx: UnboundedReceiver<LoanedItem<Vec<u8>>>,
) -> ActorResult { ) -> ActorResult {
@ -532,81 +540,69 @@ pub async fn output_loop(
} }
} }
impl Entity for TunnelRelay { impl Entity<RelayProtocol> for TunnelRelay {
fn as_any(&mut self) -> &mut dyn Any { fn message(&mut self, t: &mut Activation, m: RelayProtocol) -> ActorResult {
self match m {
} RelayProtocol::Input(RelayInput::Eof) => {
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult { t.actor.shutdown();
if let Ok(m) = tunnel_relay::RelayProtocol::try_from(&m) { }
match m { RelayProtocol::Input(RelayInput::Packet(bs)) => {
tunnel_relay::RelayProtocol::Input(b) => match *b { let mut src = BytesBinarySource::new(&bs);
tunnel_relay::Input::Eof => { let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes);
t.actor.shutdown(); let mut r = src.packed::<_, _Any, _>(&mut dec);
} let item = P::Packet::deserialize(&mut r)?;
tunnel_relay::Input::Packet { bs } => { self.handle_inbound_packet(t, item)?;
let mut src = BytesBinarySource::new(&bs); }
RelayProtocol::Input(RelayInput::Segment(bs)) => {
self.input_buffer.extend_from_slice(&bs);
loop {
let (e, count) = {
let mut src = BytesBinarySource::new(&self.input_buffer);
let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes); let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes);
let mut r = src.packed::<_, _Any, _>(&mut dec); let mut r = src.packed::<_, _Any, _>(&mut dec);
let item = P::Packet::deserialize(&mut r)?; let e = match P::Packet::deserialize(&mut r) {
self.handle_inbound_packet(t, item)?; Err(ParseError::Preserves(PreservesError::Io(e)))
} if is_eof_io_error(&e) =>
tunnel_relay::Input::Segment { bs } => { None,
self.input_buffer.extend_from_slice(&bs); result => Some(result?),
loop {
let (e, count) = {
let mut src = BytesBinarySource::new(&self.input_buffer);
let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes);
let mut r = src.packed::<_, _Any, _>(&mut dec);
let e = match P::Packet::deserialize(&mut r) {
Err(ParseError::Preserves(PreservesError::Io(e)))
if is_eof_io_error(&e) =>
None,
result => Some(result?),
};
(e, r.source.index)
};
match e {
None => break,
Some(item) => {
self.input_buffer.advance(count);
self.handle_inbound_packet(t, item)?;
}
}
}
}
}
tunnel_relay::RelayProtocol::Output(b) => match *b {
tunnel_relay::Output { oid, event } => {
if self.pending_outbound.is_empty() {
t.message_immediate_self(
&self.self_ref, &tunnel_relay::RelayProtocol::Flush);
}
let turn_event = P::TurnEvent {
oid: P::Oid(oid.0),
event: self.handle_outbound_event(t, event)?,
}; };
self.pending_outbound.push(turn_event); (e, r.source.index)
} };
} match e {
tunnel_relay::RelayProtocol::SyncGc(b) => match *b { None => break,
tunnel_relay::SyncGc { peer } => { Some(item) => {
if let Some(ws) = self.membranes.imported.ref_map.get(&peer) { self.input_buffer.advance(count);
let ws = Arc::clone(ws); // cloned to release the borrow to permit the release self.handle_inbound_packet(t, item)?;
self.membranes.imported.release(&ws);
} }
} }
} }
tunnel_relay::RelayProtocol::Flush => { }
let events = std::mem::take(&mut self.pending_outbound); RelayProtocol::Output(oid, event) => {
self.send_packet(&t.debtor, events.len(), P::Packet::Turn(Box::new(P::Turn(events))))? if self.pending_outbound.is_empty() {
t.message_immediate_self(&self.self_ref, RelayProtocol::Flush);
} }
let turn_event = P::TurnEvent {
oid: P::Oid(oid.0),
event: self.handle_outbound_event(t, event)?,
};
self.pending_outbound.push(turn_event);
}
RelayProtocol::SyncGc(peer) => {
if let Some(ws) = self.membranes.imported.ref_map.get(&peer) {
let ws = Arc::clone(ws); // cloned to release the borrow to permit the release
self.membranes.imported.release(&ws);
}
}
RelayProtocol::Flush => {
let events = std::mem::take(&mut self.pending_outbound);
self.send_packet(&t.debtor, events.len(), P::Packet::Turn(Box::new(P::Turn(events))))?
} }
} }
Ok(()) Ok(())
} }
fn exit_hook(&mut self, t: &mut Activation, exit_status: &ActorResult) -> ActorResult { fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
if let Err(e) = exit_status { if let Err(e) = &**exit_status {
let e = e.clone(); let e = e.clone();
self.send_packet(&t.debtor, 1, P::Packet::Error(Box::new(e)))?; self.send_packet(&t.debtor, 1, P::Packet::Error(Box::new(e)))?;
} }
@ -614,37 +610,30 @@ impl Entity for TunnelRelay {
} }
} }
impl Entity for RelayEntity { impl Entity<_Any> for RelayEntity {
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult { fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
Ok(t.message(&self.relay_ref, &tunnel_relay::Output { Ok(t.message(&self.relay_ref, RelayProtocol::Output(
oid: self.oid.clone(), self.oid.clone(),
event: P::Event::Assert(Box::new(P::Assert { P::Event::Assert(Box::new(P::Assert {
assertion: P::Assertion(a), assertion: P::Assertion(a),
handle: P::Handle(h.into()), handle: P::Handle(h.into()),
})), })))))
}))
} }
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult { fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
Ok(t.message(&self.relay_ref, &tunnel_relay::Output { Ok(t.message(&self.relay_ref, RelayProtocol::Output(
oid: self.oid.clone(), self.oid.clone(),
event: P::Event::Retract(Box::new(P::Retract { P::Event::Retract(Box::new(P::Retract {
handle: P::Handle(h.into()), handle: P::Handle(h.into()),
})), })))))
}))
} }
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult { fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
Ok(t.message(&self.relay_ref, &tunnel_relay::Output { Ok(t.message(&self.relay_ref, RelayProtocol::Output(
oid: self.oid.clone(), self.oid.clone(),
event: P::Event::Message(Box::new(P::Message { body: P::Assertion(m) })), P::Event::Message(Box::new(P::Message { body: P::Assertion(m) })))))
}))
} }
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult { fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
Ok(t.message(&self.relay_ref, &tunnel_relay::Output { Ok(t.message(&self.relay_ref, RelayProtocol::Output(
oid: self.oid.clone(), self.oid.clone(),
event: P::Event::Sync(Box::new(P::Sync { peer })), P::Event::Sync(Box::new(P::Sync { peer: Cap::guard(&peer) })))))
}))
} }
} }

View File

@ -1,6 +1,6 @@
use super::bag; use super::bag;
use preserves::value::{Map, Set, Value, NestedValue}; use preserves::value::{Map, NestedValue, Set, Value};
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::convert::TryInto; use std::convert::TryInto;
@ -9,7 +9,7 @@ use std::sync::Arc;
use crate::actor::_Any; use crate::actor::_Any;
use crate::actor::Activation; use crate::actor::Activation;
use crate::actor::Handle; use crate::actor::Handle;
use crate::actor::Ref; use crate::actor::Cap;
use crate::schemas::dataspace_patterns as ds; use crate::schemas::dataspace_patterns as ds;
use crate::pattern::{self, PathStep, Path, Paths}; use crate::pattern::{self, PathStep, Path, Paths};
@ -58,7 +58,7 @@ struct Leaf { // aka Topic
#[derive(Debug)] #[derive(Debug)]
struct Endpoints { struct Endpoints {
cached_captures: Bag<Captures>, cached_captures: Bag<Captures>,
endpoints: Map<Arc<Ref>, Map<Captures, Handle>>, endpoints: Map<Arc<Cap>, Map<Captures, Handle>>,
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -76,7 +76,7 @@ impl Index {
&mut self, &mut self,
t: &mut Activation, t: &mut Activation,
pat: &ds::Pattern, pat: &ds::Pattern,
observer: &Arc<Ref>, observer: &Arc<Cap>,
) { ) {
let analysis = pattern::PatternAnalysis::new(pat); let analysis = pattern::PatternAnalysis::new(pat);
self.root.extend(pat).add_observer(t, &analysis, observer); self.root.extend(pat).add_observer(t, &analysis, observer);
@ -87,7 +87,7 @@ impl Index {
&mut self, &mut self,
t: &mut Activation, t: &mut Activation,
pat: ds::Pattern, pat: ds::Pattern,
observer: &Arc<Ref>, observer: &Arc<Cap>,
) { ) {
let analysis = pattern::PatternAnalysis::new(&pat); let analysis = pattern::PatternAnalysis::new(&pat);
self.root.extend(&pat).remove_observer(t, analysis, observer); self.root.extend(&pat).remove_observer(t, analysis, observer);
@ -106,7 +106,9 @@ impl Index {
|es, cs| { |es, cs| {
if es.cached_captures.change(cs.clone(), 1) == bag::Net::AbsentToPresent { if es.cached_captures.change(cs.clone(), 1) == bag::Net::AbsentToPresent {
for (observer, capture_map) in &mut es.endpoints { for (observer, capture_map) in &mut es.endpoints {
capture_map.insert(cs.clone(), t.assert(observer, cs.clone())); if let Some(h) = observer.assert(t, cs.clone()) {
capture_map.insert(cs.clone(), h);
}
} }
} }
}) })
@ -151,7 +153,7 @@ impl Index {
|es, cs| { |es, cs| {
*delivery_count += es.endpoints.len(); *delivery_count += es.endpoints.len();
for observer in es.endpoints.keys() { for observer in es.endpoints.keys() {
t.message(observer, cs.clone()); observer.message(t, cs.clone());
} }
}).perform(&mut self.root); }).perform(&mut self.root);
} }
@ -389,7 +391,7 @@ impl Continuation {
&mut self, &mut self,
t: &mut Activation, t: &mut Activation,
analysis: &pattern::PatternAnalysis, analysis: &pattern::PatternAnalysis,
observer: &Arc<Ref>, observer: &Arc<Cap>,
) { ) {
let cached_assertions = &self.cached_assertions; let cached_assertions = &self.cached_assertions;
let const_val_map = let const_val_map =
@ -418,7 +420,9 @@ impl Continuation {
}); });
let mut capture_map = Map::new(); let mut capture_map = Map::new();
for cs in endpoints.cached_captures.keys() { for cs in endpoints.cached_captures.keys() {
capture_map.insert(cs.clone(), t.assert(observer, cs.clone())); if let Some(h) = observer.assert(t, cs.clone()) {
capture_map.insert(cs.clone(), h);
}
} }
endpoints.endpoints.insert(observer.clone(), capture_map); endpoints.endpoints.insert(observer.clone(), capture_map);
} }
@ -427,7 +431,7 @@ impl Continuation {
&mut self, &mut self,
t: &mut Activation, t: &mut Activation,
analysis: pattern::PatternAnalysis, analysis: pattern::PatternAnalysis,
observer: &Arc<Ref>, observer: &Arc<Cap>,
) { ) {
if let Entry::Occupied(mut const_val_map_entry) if let Entry::Occupied(mut const_val_map_entry)
= self.leaf_map.entry(analysis.const_paths) = self.leaf_map.entry(analysis.const_paths)

View File

@ -1,29 +1,32 @@
use crate::actor::*; use crate::actor::*;
use preserves::value::NestedValue; use std::fmt::Debug;
use std::any::Any;
use std::sync::Arc; use std::sync::Arc;
struct Tracer(tracing::Span); struct Tracer(tracing::Span);
fn set_name_oid(_ac: &mut Actor, t: &mut Tracer, r: &Arc<Ref>) { fn set_name_oid<M>(t: &mut Tracer, r: &Arc<Ref<M>>) {
t.0.record("oid", &tracing::field::display(&r.addr.oid())); t.0.record("oid", &tracing::field::display(&r.oid()));
} }
pub fn tracer(ac: &mut Actor, name: tracing::Span) -> Arc<Ref> { pub fn tracer<M: Debug>(ac: &mut Actor, name: tracing::Span) -> Arc<Ref<M>> {
ac.create_rec(Tracer(name), set_name_oid) let mut e = Tracer(name);
let r = ac.create_inert();
set_name_oid(&mut e, &r);
r.become_entity(e);
r
} }
pub fn tracer_top(name: tracing::Span) -> Arc<Ref> { pub fn tracer_top<M: Debug>(name: tracing::Span) -> Arc<Ref<M>> {
Actor::create_and_start_rec(crate::name!(parent: None, "tracer"), Tracer(name), set_name_oid) let mut e = Tracer(name);
let r = Actor::create_and_start_inert(crate::name!(parent: None, "tracer"));
set_name_oid(&mut e, &r);
r.become_entity(e);
r
} }
impl Entity for Tracer { impl<M: Debug> Entity<M> for Tracer {
fn as_any(&mut self) -> &mut dyn Any { fn assert(&mut self, _t: &mut Activation, a: M, h: Handle) -> ActorResult {
self
}
fn assert(&mut self, _t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
let _guard = self.0.enter(); let _guard = self.0.enter();
tracing::trace!(a = debug(&a), h = debug(&h), "assert"); tracing::trace!(a = debug(&a), h = debug(&h), "assert");
Ok(()) Ok(())
@ -33,15 +36,15 @@ impl Entity for Tracer {
tracing::trace!(h = debug(&h), "retract"); tracing::trace!(h = debug(&h), "retract");
Ok(()) Ok(())
} }
fn message(&mut self, _t: &mut Activation, m: _Any) -> ActorResult { fn message(&mut self, _t: &mut Activation, m: M) -> ActorResult {
let _guard = self.0.enter(); let _guard = self.0.enter();
tracing::trace!(m = debug(&m), "message"); tracing::trace!(m = debug(&m), "message");
Ok(()) Ok(())
} }
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult { fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
let _guard = self.0.enter(); let _guard = self.0.enter();
tracing::trace!(peer = debug(&peer), "sync"); tracing::trace!(peer = debug(&peer), "sync");
t.message(&peer, _Any::new(true)); t.message(&peer, Synced);
Ok(()) Ok(())
} }
} }