Typed Refs (!). Decent speedup by avoiding marshalling
This commit is contained in:
parent
f0a9894ee8
commit
d85b980834
|
@ -1,6 +1,5 @@
|
|||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use std::any::Any;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
|
@ -29,10 +28,7 @@ fn says(who: _Any, what: _Any) -> _Any {
|
|||
|
||||
struct ShutdownEntity;
|
||||
|
||||
impl Entity for ShutdownEntity {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
impl Entity<_Any> for ShutdownEntity {
|
||||
fn message(&mut self, t: &mut Activation, _m: _Any) -> ActorResult {
|
||||
t.actor.shutdown();
|
||||
Ok(())
|
||||
|
@ -63,12 +59,12 @@ pub fn bench_pub(c: &mut Criterion) {
|
|||
ac.linked_task(syndicate::name!("sender"), async move {
|
||||
for _ in 0..iters {
|
||||
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(
|
||||
|e| e.message(t, says(_Any::new("bench_pub"),
|
||||
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(
|
||||
|e| e.message(t, _Any::new(true)))))?;
|
||||
Ok(())
|
||||
|
@ -83,14 +79,11 @@ pub fn bench_pub(c: &mut Criterion) {
|
|||
b.iter_custom(|iters| {
|
||||
let start = Instant::now();
|
||||
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));
|
||||
|
||||
struct Receiver(Arc<AtomicU64>);
|
||||
impl Entity for Receiver {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
impl Entity<_Any> for Receiver {
|
||||
fn message(&mut self, _t: &mut Activation, _m: _Any) -> ActorResult {
|
||||
self.0.fetch_add(1, Ordering::Relaxed);
|
||||
Ok(())
|
||||
|
@ -98,13 +91,13 @@ pub fn bench_pub(c: &mut Criterion) {
|
|||
}
|
||||
|
||||
let mut ac = Actor::new();
|
||||
let shutdown = ac.create(ShutdownEntity);
|
||||
let receiver = ac.create(Receiver(Arc::clone(&turn_count)));
|
||||
let shutdown = Cap::new(&ac.create(ShutdownEntity));
|
||||
let receiver = Cap::new(&ac.create(Receiver(Arc::clone(&turn_count))));
|
||||
|
||||
{
|
||||
let iters = iters.clone();
|
||||
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 {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("Says").wrap(),
|
||||
|
@ -122,7 +115,7 @@ pub fn bench_pub(c: &mut Criterion) {
|
|||
})),
|
||||
observer: receiver,
|
||||
});
|
||||
t.assert(&ds, &Observe {
|
||||
ds.assert(t, &Observe {
|
||||
pattern: p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "shutdownTrigger".to_owned(),
|
||||
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 {
|
||||
for _ in 0..iters {
|
||||
let ds = Arc::clone(&ds);
|
||||
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||
move |t| ds.with_entity(
|
||||
external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
|
||||
move |t| ds.underlying.with_entity(
|
||||
|e| e.message(t, says(_Any::new("bench_pub"),
|
||||
Value::ByteString(vec![]).wrap())))))?
|
||||
}
|
||||
{
|
||||
let ds = Arc::clone(&ds);
|
||||
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||
move |t| ds.with_entity(
|
||||
external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
|
||||
move |t| ds.underlying.with_entity(
|
||||
|e| e.message(t, _Any::new(true)))))?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
3
build.rs
3
build.rs
|
@ -11,8 +11,7 @@ fn main() -> Result<(), Error> {
|
|||
let mut c = CompilerConfig::new(gen_dir, "crate::schemas".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(),
|
||||
"local-protocols/schema-bundle.bin".to_owned()])?;
|
||||
let inputs = expand_inputs(&vec!["protocols/schema-bundle.bin".to_owned()])?;
|
||||
c.load_schemas_and_bundles(&inputs)?;
|
||||
compile(&c)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
relay::connect_stream(t, i, o, sturdyref, (), |_state, t, ds| {
|
||||
let consumer = syndicate::entity(0)
|
||||
.on_message(|message_count, _t, m| {
|
||||
.on_message(|message_count, _t, m: _Any| {
|
||||
if m.value().is_boolean() {
|
||||
tracing::info!("{:?} messages in the last second", message_count);
|
||||
*message_count = 0;
|
||||
|
@ -41,9 +41,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
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 {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("Says").wrap(),
|
||||
|
@ -68,9 +68,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
loop {
|
||||
stats_timer.tick().await;
|
||||
let consumer = Arc::clone(&consumer);
|
||||
external_event(&Arc::clone(&consumer),
|
||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||
&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)))))?;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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_batch_count: usize = 0;
|
||||
let mut current_reply = None;
|
||||
syndicate::entity(Arc::clone(&*INERT_REF))
|
||||
.on_message(move |self_ref, t, m| {
|
||||
match m.value().as_boolean() {
|
||||
Some(true) => {
|
||||
tracing::info!("{:?} turns, {:?} events in the last second",
|
||||
turn_counter,
|
||||
event_counter);
|
||||
turn_counter = 0;
|
||||
event_counter = 0;
|
||||
}
|
||||
Some(false) => {
|
||||
current_reply = None;
|
||||
}
|
||||
None => {
|
||||
event_counter += 1;
|
||||
let bindings = m.value().to_sequence()?;
|
||||
let timestamp = &bindings[0];
|
||||
let padding = &bindings[1];
|
||||
let self_ref = t.actor.create_inert();
|
||||
self_ref.become_entity(
|
||||
syndicate::entity(Arc::clone(&self_ref))
|
||||
.on_message(move |self_ref, t, m: _Any| {
|
||||
match m.value().as_boolean() {
|
||||
Some(true) => {
|
||||
tracing::info!("{:?} turns, {:?} events in the last second",
|
||||
turn_counter,
|
||||
event_counter);
|
||||
turn_counter = 0;
|
||||
event_counter = 0;
|
||||
}
|
||||
Some(false) => {
|
||||
current_reply = None;
|
||||
}
|
||||
None => {
|
||||
event_counter += 1;
|
||||
let bindings = m.value().to_sequence()?;
|
||||
let timestamp = &bindings[0];
|
||||
let padding = &bindings[1];
|
||||
|
||||
if should_echo || (report_latency_every == 0) {
|
||||
t.message(&ds, simple_record2(&send_label,
|
||||
timestamp.clone(),
|
||||
padding.clone()));
|
||||
} else {
|
||||
if let None = current_reply {
|
||||
turn_counter += 1;
|
||||
t.message_immediate_self(&self_ref, _Any::new(false));
|
||||
let rtt_ns = now() - timestamp.value().to_u64()?;
|
||||
rtt_ns_samples[rtt_batch_count] = rtt_ns;
|
||||
rtt_batch_count += 1;
|
||||
if should_echo || (report_latency_every == 0) {
|
||||
ds.message(t, simple_record2(&send_label,
|
||||
timestamp.clone(),
|
||||
padding.clone()));
|
||||
} else {
|
||||
if let None = current_reply {
|
||||
turn_counter += 1;
|
||||
t.message_immediate_self(&self_ref, _Any::new(false));
|
||||
let rtt_ns = now() - timestamp.value().to_u64()?;
|
||||
rtt_ns_samples[rtt_batch_count] = rtt_ns;
|
||||
rtt_batch_count += 1;
|
||||
|
||||
if rtt_batch_count == report_latency_every {
|
||||
rtt_ns_samples.sort();
|
||||
report_latencies(&rtt_ns_samples);
|
||||
rtt_batch_count = 0;
|
||||
if rtt_batch_count == report_latency_every {
|
||||
rtt_ns_samples.sort();
|
||||
report_latencies(&rtt_ns_samples);
|
||||
rtt_batch_count = 0;
|
||||
}
|
||||
|
||||
current_reply = Some(
|
||||
simple_record2(&send_label,
|
||||
Value::from(now()).wrap(),
|
||||
padding.clone()));
|
||||
}
|
||||
|
||||
current_reply = Some(
|
||||
simple_record2(&send_label,
|
||||
Value::from(now()).wrap(),
|
||||
padding.clone()));
|
||||
ds.message(t, current_reply.as_ref().expect("some reply").clone());
|
||||
}
|
||||
t.message(&ds, current_reply.as_ref().expect("some reply").clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.create_rec(t.actor, |_ac, self_ref, e_ref| *self_ref = Arc::clone(e_ref))
|
||||
Ok(())
|
||||
}));
|
||||
Cap::new(&self_ref)
|
||||
};
|
||||
|
||||
t.assert(&ds, &Observe {
|
||||
ds.assert(t, &Observe {
|
||||
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol(recv_label).wrap(),
|
||||
|
@ -190,9 +192,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
loop {
|
||||
stats_timer.tick().await;
|
||||
let consumer = Arc::clone(&consumer);
|
||||
external_event(&Arc::clone(&consumer),
|
||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||
&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)))))?;
|
||||
}
|
||||
});
|
||||
|
@ -211,10 +213,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
for _ in 0..action_count {
|
||||
let ds = Arc::clone(&ds);
|
||||
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))));
|
||||
}
|
||||
external_events(&ds, &debtor, events)?
|
||||
external_events(&ds.underlying.mailbox, &debtor, events)?
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
|
|
@ -48,10 +48,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
for _ in 0..action_count {
|
||||
let ds = Arc::clone(&ds);
|
||||
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)))));
|
||||
}
|
||||
external_events(&ds, &debtor, events)?;
|
||||
external_events(&ds.underlying.mailbox, &debtor, events)?;
|
||||
}
|
||||
});
|
||||
Ok(None)
|
||||
|
|
|
@ -60,10 +60,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
s.arrival_counter = 0;
|
||||
s.departure_counter = 0;
|
||||
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 {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("Present").wrap(),
|
||||
|
@ -84,9 +84,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
loop {
|
||||
stats_timer.tick().await;
|
||||
let consumer = Arc::clone(&consumer);
|
||||
external_event(&Arc::clone(&consumer),
|
||||
external_event(&Arc::clone(&consumer.underlying.mailbox),
|
||||
&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)))))?;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -33,14 +33,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let ds = Arc::clone(&ds);
|
||||
let presence = presence.clone();
|
||||
let handle = handle.clone();
|
||||
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||
move |t| ds.with_entity(|e| e.assert(t, presence, handle))))
|
||||
external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
|
||||
move |t| ds.underlying.with_entity(|e| e.assert(t, presence, handle))))
|
||||
};
|
||||
let retract_e = || {
|
||||
let ds = Arc::clone(&ds);
|
||||
let handle = handle.clone();
|
||||
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||
move |t| ds.with_entity(|e| e.retract(t, handle))))
|
||||
external_event(&Arc::clone(&ds.underlying.mailbox), &debtor, Box::new(
|
||||
move |t| ds.underlying.with_entity(|e| e.retract(t, handle))))
|
||||
};
|
||||
assert_e()?;
|
||||
loop {
|
||||
|
|
|
@ -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 $@
|
|
@ -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„„„„„
|
|
@ -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>.
|
485
src/actor.rs
485
src/actor.rs
|
@ -13,14 +13,16 @@ use preserves::value::Domain;
|
|||
use preserves::value::IOValue;
|
||||
use preserves::value::Map;
|
||||
use preserves::value::NestedValue;
|
||||
use preserves_schema::support::ParseError;
|
||||
|
||||
use std::any::Any;
|
||||
use std::boxed::Box;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
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::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
|
||||
|
@ -34,33 +36,33 @@ pub type Handle = u64;
|
|||
pub type ActorResult = Result<(), Error>;
|
||||
pub type ActorHandle = tokio::task::JoinHandle<ActorResult>;
|
||||
|
||||
pub trait Entity: Send + std::marker::Sync {
|
||||
fn as_any(&mut self) -> &mut dyn Any;
|
||||
pub struct Synced;
|
||||
|
||||
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(())
|
||||
}
|
||||
fn retract(&mut self, _t: &mut Activation, _h: Handle) -> ActorResult {
|
||||
Ok(())
|
||||
}
|
||||
fn message(&mut self, _t: &mut Activation, _m: _Any) -> ActorResult {
|
||||
fn message(&mut self, _t: &mut Activation, _m: M) -> ActorResult {
|
||||
Ok(())
|
||||
}
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult {
|
||||
t.message(&peer, _Any::new(true));
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
|
||||
t.message(&peer, Synced);
|
||||
Ok(())
|
||||
}
|
||||
fn turn_end(&mut self, _t: &mut Activation) -> ActorResult {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
enum Destination {
|
||||
ImmediateSelf(Action),
|
||||
Remote(Arc<Ref>, Action),
|
||||
Remote(Arc<Mailbox>, Action),
|
||||
}
|
||||
|
||||
type OutboundAssertions = Map<Handle, Destination>;
|
||||
|
@ -98,84 +100,45 @@ enum SystemMessage {
|
|||
|
||||
pub struct Mailbox {
|
||||
pub actor_id: ActorId,
|
||||
pub mailbox_id: u64,
|
||||
tx: UnboundedSender<SystemMessage>,
|
||||
mailbox_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
pub struct Actor {
|
||||
actor_id: ActorId,
|
||||
tx: UnboundedSender<SystemMessage>,
|
||||
mailbox: Weak<Mailbox>,
|
||||
rx: Option<UnboundedReceiver<SystemMessage>>,
|
||||
mailbox_count: Arc<AtomicUsize>,
|
||||
outbound_assertions: OutboundAssertions,
|
||||
next_task_id: u64,
|
||||
linked_tasks: Map<u64, CancellationToken>,
|
||||
exit_hooks: Vec<Arc<Ref>>,
|
||||
exit_hooks: Vec<Action>,
|
||||
exit_status: Option<Arc<ActorResult>>,
|
||||
}
|
||||
|
||||
pub struct ObjectAddress {
|
||||
pub mailbox: Mailbox,
|
||||
pub target: RwLock<Box<dyn Entity>>,
|
||||
pub struct Ref<M> {
|
||||
pub mailbox: Arc<Mailbox>,
|
||||
pub target: RwLock<Option<Box<dyn Entity<M>>>>,
|
||||
}
|
||||
|
||||
impl ObjectAddress {
|
||||
pub fn oid(&self) -> usize {
|
||||
std::ptr::addr_of!(*self) as usize
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Cap {
|
||||
pub underlying: Arc<Ref<_Any>>,
|
||||
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);
|
||||
|
||||
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 = {
|
||||
let credit =
|
||||
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> {
|
||||
pub fn new(actor: &'activation mut Actor, debtor: Arc<Debtor>) -> Self {
|
||||
Activation {
|
||||
|
@ -214,47 +194,43 @@ impl<'activation> Activation<'activation> {
|
|||
}
|
||||
}
|
||||
|
||||
fn immediate_oid(&self, r: &Arc<Ref>) {
|
||||
if r.addr.mailbox.actor_id != self.actor.actor_id {
|
||||
fn immediate_oid<M>(&self, r: &Arc<Ref<M>>) {
|
||||
if r.mailbox.actor_id != self.actor.actor_id {
|
||||
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();
|
||||
if let Some(assertion) = r.rewrite(a.into()) {
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.queue_for(&r).push(Box::new(
|
||||
move |t| r.with_entity(|e| e.assert(t, assertion, handle))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.actor.outbound_assertions.insert(
|
||||
handle,
|
||||
Destination::Remote(Arc::clone(&r), Box::new(
|
||||
move |t| r.with_entity(|e| e.retract(t, handle)))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.queue_for(&r).push(Box::new(
|
||||
move |t| r.with_entity(|e| e.assert(t, a, handle))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.actor.outbound_assertions.insert(
|
||||
handle,
|
||||
Destination::Remote(Arc::clone(&r.mailbox), Box::new(
|
||||
move |t| r.with_entity(|e| e.retract(t, 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);
|
||||
let handle = crate::next_handle();
|
||||
if let Some(assertion) = r.rewrite(a.into()) {
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.immediate_self.push(Box::new(
|
||||
move |t| r.with_entity(|e| e.assert(t, assertion, handle))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.actor.outbound_assertions.insert(
|
||||
handle,
|
||||
Destination::ImmediateSelf(Box::new(
|
||||
move |t| r.with_entity(|e| e.retract(t, handle)))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.immediate_self.push(Box::new(
|
||||
move |t| r.with_entity(|e| e.assert(t, a, handle))));
|
||||
}
|
||||
{
|
||||
let r = Arc::clone(r);
|
||||
self.actor.outbound_assertions.insert(
|
||||
handle,
|
||||
Destination::ImmediateSelf(Box::new(
|
||||
move |t| r.with_entity(|e| e.retract(t, handle)))));
|
||||
}
|
||||
handle
|
||||
}
|
||||
|
@ -267,39 +243,39 @@ impl<'activation> Activation<'activation> {
|
|||
|
||||
fn retract_known_ref(&mut self, d: Destination) {
|
||||
match d {
|
||||
Destination::Remote(r, action) =>
|
||||
self.queue_for(&r).push(action),
|
||||
Destination::Remote(mailbox, action) =>
|
||||
self.queue_for_mailbox(&mailbox).push(action),
|
||||
Destination::ImmediateSelf(action) =>
|
||||
self.immediate_self.push(action),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> {
|
||||
if let Some(body) = r.rewrite(m.into()) {
|
||||
let r = Arc::clone(r);
|
||||
self.queue_for(&r).push(Box::new(
|
||||
move |t| r.with_entity(|e| e.message(t, body))))
|
||||
}
|
||||
pub fn message<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>, m: M) {
|
||||
let r = Arc::clone(r);
|
||||
self.queue_for(&r).push(Box::new(
|
||||
move |t| r.with_entity(|e| e.message(t, m))))
|
||||
}
|
||||
|
||||
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);
|
||||
if let Some(body) = r.rewrite(m.into()) {
|
||||
let r = Arc::clone(r);
|
||||
self.immediate_self.push(Box::new(
|
||||
move |t| r.with_entity(|e| e.message(t, body))))
|
||||
}
|
||||
let r = Arc::clone(r);
|
||||
self.immediate_self.push(Box::new(
|
||||
move |t| r.with_entity(|e| e.message(t, m))))
|
||||
}
|
||||
|
||||
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);
|
||||
self.queue_for(&r).push(Box::new(
|
||||
move |t| r.with_entity(|e| e.sync(t, peer))))
|
||||
}
|
||||
|
||||
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut PendingEventQueue {
|
||||
&mut self.queues.entry(r.addr.mailbox.actor_id)
|
||||
.or_insert((r.addr.mailbox.tx.clone(), Vec::new())).1
|
||||
fn queue_for<M>(&mut self, r: &Arc<Ref<M>>) -> &mut PendingEventQueue {
|
||||
self.queue_for_mailbox(&r.mailbox)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -389,26 +365,26 @@ fn send_actions(
|
|||
|
||||
impl std::fmt::Debug for Mailbox {
|
||||
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 {
|
||||
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 PartialEq for Mailbox {
|
||||
fn eq(&self, other: &Mailbox) -> bool {
|
||||
self.mailbox_id == other.mailbox_id
|
||||
self.actor_id == other.actor_id
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Mailbox {
|
||||
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 {
|
||||
fn drop(&mut self) {
|
||||
let old_mailbox_refcount = self.mailbox_count.fetch_sub(1, Ordering::SeqCst);
|
||||
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);
|
||||
()
|
||||
}
|
||||
let _ = self.tx.send(SystemMessage::Release);
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,29 +410,27 @@ impl Actor {
|
|||
actor_id,
|
||||
tx,
|
||||
rx: Some(rx),
|
||||
mailbox_count: Arc::new(AtomicUsize::new(0)),
|
||||
mailbox: Weak::new(),
|
||||
outbound_assertions: Map::new(),
|
||||
next_task_id: 0,
|
||||
linked_tasks: Map::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,
|
||||
e: E,
|
||||
) -> Arc<Ref> {
|
||||
Self::create_and_start_rec(name, e, |_, _, _| ())
|
||||
) -> Arc<Ref<M>> {
|
||||
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,
|
||||
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>(
|
||||
name: tracing::Span,
|
||||
e: E,
|
||||
f: F,
|
||||
) -> Arc<Ref> {
|
||||
pub fn create_and_start_inert<M>(name: tracing::Span) -> Arc<Ref<M>> {
|
||||
let mut ac = Self::new();
|
||||
let r = ac.create_rec(e, f);
|
||||
let r = ac.create_inert();
|
||||
ac.start(name);
|
||||
r
|
||||
}
|
||||
|
@ -488,17 +439,18 @@ impl Actor {
|
|||
self.actor_id
|
||||
}
|
||||
|
||||
fn mailbox(&mut self) -> Mailbox {
|
||||
let _old_refcount = self.mailbox_count.fetch_add(1, Ordering::SeqCst);
|
||||
let new_mailbox = Mailbox {
|
||||
actor_id: self.actor_id,
|
||||
mailbox_id: crate::next_mailbox_id(),
|
||||
tx: self.tx.clone(),
|
||||
mailbox_count: Arc::clone(&self.mailbox_count),
|
||||
};
|
||||
// tracing::trace!(new_mailbox = debug(&new_mailbox),
|
||||
// new_mailbox_refcount = debug(_old_refcount + 1));
|
||||
new_mailbox
|
||||
fn mailbox(&mut self) -> Arc<Mailbox> {
|
||||
match self.mailbox.upgrade() {
|
||||
None => {
|
||||
let new_mailbox = Arc::new(Mailbox {
|
||||
actor_id: self.actor_id,
|
||||
tx: self.tx.clone(),
|
||||
});
|
||||
self.mailbox = Arc::downgrade(&new_mailbox);
|
||||
new_mailbox
|
||||
}
|
||||
Some(m) => m
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
self.create_rec(e, |_, _, _| ())
|
||||
pub fn create<M, E: Entity<M> + Send + Sync + 'static>(&mut self, e: E) -> Arc<Ref<M>> {
|
||||
let r = self.create_inert();
|
||||
r.become_entity(e);
|
||||
r
|
||||
}
|
||||
|
||||
pub fn create_rec<E: Entity + Send + std::marker::Sync + 'static,
|
||||
F: FnOnce(&mut Self, &mut E, &Arc<Ref>) -> ()>(
|
||||
&mut self,
|
||||
e: E,
|
||||
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 create_inert<M>(&mut self) -> Arc<Ref<M>> {
|
||||
Arc::new(Ref {
|
||||
mailbox: self.mailbox(),
|
||||
target: RwLock::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
tracing::trace!("start");
|
||||
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")));
|
||||
for r in std::mem::take(&mut t.actor.exit_hooks) {
|
||||
if let Err(err) = r.with_entity(|e| e.exit_hook(&mut t, &result)) {
|
||||
tracing::error!(err = debug(err),
|
||||
r = debug(&r),
|
||||
"error in exit hook");
|
||||
for action in std::mem::take(&mut t.actor.exit_hooks) {
|
||||
if let Err(err) = action(&mut t) {
|
||||
tracing::error!(err = debug(err), "error in exit hook");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -583,8 +526,12 @@ impl Actor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_exit_hook(&mut self, r: &Arc<Ref>) {
|
||||
self.exit_hooks.push(Arc::clone(r))
|
||||
pub fn add_exit_hook<M: 'static + Send + Sync>(&mut self, r: &Arc<Ref<M>>) {
|
||||
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> {
|
||||
|
@ -673,25 +620,89 @@ impl Drop for Actor {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn external_event(r: &Arc<Ref>, debtor: &Arc<Debtor>, action: Action) -> ActorResult {
|
||||
send_actions(&r.addr.mailbox.tx, debtor, vec![action])
|
||||
pub fn external_event(mailbox: &Arc<Mailbox>, debtor: &Arc<Debtor>, action: Action) -> ActorResult {
|
||||
send_actions(&mailbox.tx, debtor, vec![action])
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn external_events(r: &Arc<Ref>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult {
|
||||
send_actions(&r.addr.mailbox.tx, debtor, events)
|
||||
pub fn external_events(mailbox: &Arc<Mailbox>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult {
|
||||
send_actions(&mailbox.tx, debtor, events)
|
||||
}
|
||||
|
||||
impl Ref {
|
||||
pub fn with_entity<R, F: FnOnce(&mut dyn Entity) -> R>(&self, f: F) -> R {
|
||||
f(&mut **self.addr.target.write().expect("unpoisoned"))
|
||||
impl<M> Ref<M> {
|
||||
pub fn become_entity<E: 'static + Entity<M>>(&self, e: E) {
|
||||
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> {
|
||||
let mut r = Ref {
|
||||
addr: Arc::clone(&self.addr),
|
||||
attenuation: self.attenuation.clone(),
|
||||
};
|
||||
let mut r = Cap { attenuation: self.attenuation.clone(), .. self.clone() };
|
||||
r.attenuation.extend(attenuation.check()?);
|
||||
Ok(Arc::new(r))
|
||||
}
|
||||
|
@ -705,33 +716,77 @@ impl Ref {
|
|||
}
|
||||
Some(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Ref {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
if self.attenuation.is_empty() {
|
||||
write!(f, "⌜{}:{:016x}⌝", self.addr.mailbox.actor_id, self.addr.oid())
|
||||
} else {
|
||||
write!(f, "⌜{}:{:016x}\\{:?}⌝", self.addr.mailbox.actor_id, self.addr.oid(), self.attenuation)
|
||||
pub fn assert<M: Into<_Any>>(&self, t: &mut Activation, m: M) -> Option<Handle> {
|
||||
self.rewrite(m.into()).map(|m| t.assert(&self.underlying, m))
|
||||
}
|
||||
|
||||
pub fn message<M: Into<_Any>>(&self, t: &mut Activation, m: M) {
|
||||
if let Some(m) = self.rewrite(m.into()) {
|
||||
t.message(&self.underlying, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Domain for Ref {}
|
||||
|
||||
impl std::convert::TryFrom<&IOValue> for Ref {
|
||||
type Error = preserves_schema::support::ParseError;
|
||||
fn try_from(_v: &IOValue) -> Result<Self, Self::Error> {
|
||||
panic!("Attempted to serialize Ref via IOValue");
|
||||
impl std::fmt::Debug for Cap {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
if self.attenuation.is_empty() {
|
||||
self.underlying.fmt(f)
|
||||
} else {
|
||||
write!(f, "⌜{}:{:016x}\\{:?}⌝",
|
||||
self.underlying.mailbox.actor_id,
|
||||
self.underlying.oid(),
|
||||
self.attenuation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<&Ref> for IOValue {
|
||||
fn from(_v: &Ref) -> IOValue {
|
||||
impl Domain for Cap {}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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_rules! name {
|
||||
() => {tracing::info_span!(actor_id = tracing::field::Empty,
|
||||
|
|
|
@ -5,8 +5,6 @@ use preserves::value::Map;
|
|||
use preserves::value::NestedValue;
|
||||
use preserves::value::Value;
|
||||
|
||||
use std::any::Any;
|
||||
use std::convert::TryFrom;
|
||||
use std::future::ready;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
@ -21,6 +19,7 @@ use syndicate::error::error;
|
|||
use syndicate::config;
|
||||
use syndicate::relay;
|
||||
use syndicate::schemas::internal_protocol::_Any;
|
||||
use syndicate::schemas::gatekeeper;
|
||||
use syndicate::sturdy;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
|
@ -72,10 +71,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
tracing::trace!("startup");
|
||||
|
||||
let ds = Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new());
|
||||
let gateway = Actor::create_and_start(
|
||||
let ds = Cap::new(&Actor::create_and_start(syndicate::name!("dataspace"), Dataspace::new()));
|
||||
let gateway = Cap::guard(&Actor::create_and_start(
|
||||
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);
|
||||
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);
|
||||
tracing::info!(rootcap = debug(&_Any::from(&sr)));
|
||||
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(())
|
||||
}));
|
||||
}
|
||||
|
@ -131,7 +130,7 @@ fn extract_binary_packets(
|
|||
async fn run_connection(
|
||||
t: &mut Activation<'_>,
|
||||
stream: TcpStream,
|
||||
gateway: Arc<Ref>,
|
||||
gateway: Arc<Cap>,
|
||||
addr: std::net::SocketAddr,
|
||||
config: Arc<config::ServerConfig>,
|
||||
) -> ActorResult {
|
||||
|
@ -158,11 +157,8 @@ async fn run_connection(
|
|||
_ => unreachable!()
|
||||
};
|
||||
struct ExitListener;
|
||||
impl Entity for ExitListener {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn exit_hook(&mut self, _t: &mut Activation, exit_status: &ActorResult) -> ActorResult {
|
||||
impl Entity<()> for ExitListener {
|
||||
fn exit_hook(&mut self, _t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
||||
tracing::info!(exit_status = debug(exit_status), "disconnect");
|
||||
Ok(())
|
||||
}
|
||||
|
@ -174,7 +170,7 @@ async fn run_connection(
|
|||
}
|
||||
|
||||
async fn run_listener(
|
||||
gateway: Arc<Ref>,
|
||||
gateway: Arc<Cap>,
|
||||
port: u16,
|
||||
config: Arc<config::ServerConfig>,
|
||||
) -> 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_patterns as p;
|
||||
use syndicate::schemas::gatekeeper;
|
||||
match gatekeeper::Resolve::try_from(&a) {
|
||||
Err(_) => Ok(None),
|
||||
Ok(gatekeeper::Resolve { sturdyref, observer }) => {
|
||||
let queried_oid = sturdyref.oid.clone();
|
||||
let handler = syndicate::entity(observer)
|
||||
.on_asserted(move |observer, t, a| {
|
||||
let bindings = a.value().to_sequence()?;
|
||||
let key = bindings[0].value().to_bytestring()?;
|
||||
let unattenuated_target = bindings[1].value().to_embedded()?;
|
||||
match sturdyref.validate_and_attenuate(key, unattenuated_target) {
|
||||
Err(e) => {
|
||||
tracing::warn!(sturdyref = debug(&_Any::from(&sturdyref)),
|
||||
"sturdyref failed validation: {}", e);
|
||||
Ok(None)
|
||||
},
|
||||
Ok(target) => {
|
||||
tracing::trace!(sturdyref = debug(&_Any::from(&sturdyref)),
|
||||
target = debug(&target),
|
||||
"sturdyref resolved");
|
||||
let h = t.assert(observer, _Any::domain(target));
|
||||
Ok(Some(Box::new(move |_observer, t| Ok(t.retract(h)))))
|
||||
}
|
||||
|
||||
let gatekeeper::Resolve { sturdyref, observer } = a;
|
||||
let queried_oid = sturdyref.oid.clone();
|
||||
let handler = syndicate::entity(observer)
|
||||
.on_asserted(move |observer, t, a: _Any| {
|
||||
let bindings = a.value().to_sequence()?;
|
||||
let key = bindings[0].value().to_bytestring()?;
|
||||
let unattenuated_target = bindings[1].value().to_embedded()?;
|
||||
match sturdyref.validate_and_attenuate(key, unattenuated_target) {
|
||||
Err(e) => {
|
||||
tracing::warn!(sturdyref = debug(&_Any::from(&sturdyref)),
|
||||
"sturdyref failed validation: {}", e);
|
||||
Ok(None)
|
||||
},
|
||||
Ok(target) => {
|
||||
tracing::trace!(sturdyref = debug(&_Any::from(&sturdyref)),
|
||||
target = debug(&target),
|
||||
"sturdyref resolved");
|
||||
if let Some(h) = observer.assert(t, _Any::domain(target)) {
|
||||
Ok(Some(Box::new(move |_observer, t| Ok(t.retract(h)))))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
})
|
||||
.create(t.actor);
|
||||
let oh = t.assert(ds, &dataspace::Observe {
|
||||
// TODO: codegen plugin to generate pattern constructors
|
||||
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("bind").wrap(),
|
||||
arity: 3.into(),
|
||||
}),
|
||||
members: Map::from_iter(vec![
|
||||
(0.into(), p::Pattern::DLit(Box::new(p::DLit {
|
||||
value: queried_oid,
|
||||
}))),
|
||||
(1.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "key".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
(2.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "target".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
].into_iter())
|
||||
})),
|
||||
observer: handler,
|
||||
});
|
||||
Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh)))))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.create_cap(t.actor);
|
||||
if let Some(oh) = ds.assert(t, &dataspace::Observe {
|
||||
// TODO: codegen plugin to generate pattern constructors
|
||||
pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec {
|
||||
ctor: Box::new(p::CRec {
|
||||
label: Value::symbol("bind").wrap(),
|
||||
arity: 3.into(),
|
||||
}),
|
||||
members: Map::from_iter(vec![
|
||||
(0.into(), p::Pattern::DLit(Box::new(p::DLit {
|
||||
value: queried_oid,
|
||||
}))),
|
||||
(1.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "key".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
(2.into(), p::Pattern::DBind(Box::new(p::DBind {
|
||||
name: "target".to_owned(),
|
||||
pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)),
|
||||
}))),
|
||||
].into_iter())
|
||||
})),
|
||||
observer: handler,
|
||||
}) {
|
||||
Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh)))))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use super::schemas::dataspace::_Any;
|
|||
|
||||
use preserves::value::Map;
|
||||
|
||||
use std::any::Any;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -68,10 +67,7 @@ impl Dataspace {
|
|||
}
|
||||
}
|
||||
|
||||
impl Entity for Dataspace {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
impl Entity<_Any> for Dataspace {
|
||||
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
||||
// tracing::trace!(assertion = debug(&a), handle = debug(&h), "assert");
|
||||
|
||||
|
|
|
@ -3,26 +3,25 @@ use crate::error::Error;
|
|||
|
||||
use preserves::value::Map;
|
||||
|
||||
use std::any::Any;
|
||||
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 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> =
|
||||
Result<Option<Box<dyn 'static + Send + Sync + FnOnce(&mut E, &mut Activation) -> ActorResult>>,
|
||||
Error>;
|
||||
|
||||
pub struct DuringEntity<E, Fa, Fm>
|
||||
pub struct DuringEntity<M, E, Fa, Fm>
|
||||
where
|
||||
M: 'static + Send + Sync,
|
||||
E: 'static + Send + Sync,
|
||||
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>,
|
||||
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult,
|
||||
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||
{
|
||||
state: E,
|
||||
assertion_handler: Option<Fa>,
|
||||
message_handler: Option<Fm>,
|
||||
during: During<E>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
|
||||
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
|
||||
) -> DuringEntity<E,
|
||||
fn (&mut E, &mut Activation, _Any) -> DuringResult<E>,
|
||||
fn (&mut E, &mut Activation, _Any) -> ActorResult>
|
||||
) -> DuringEntity<M,
|
||||
E,
|
||||
fn (&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||
fn (&mut E, &mut Activation, M) -> ActorResult>
|
||||
where
|
||||
E: 'static + Send + Sync,
|
||||
{
|
||||
DuringEntity::new(state, None, None)
|
||||
}
|
||||
|
||||
impl<E, Fa, Fm> DuringEntity<E, Fa, Fm>
|
||||
impl<M, E, Fa, Fm> DuringEntity<M, E, Fa, Fm>
|
||||
where
|
||||
M: 'static + Send + Sync,
|
||||
E: 'static + Send + Sync,
|
||||
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>,
|
||||
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult,
|
||||
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||
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 {
|
||||
DuringEntity {
|
||||
|
@ -67,56 +68,61 @@ where
|
|||
assertion_handler,
|
||||
message_handler,
|
||||
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
|
||||
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 {
|
||||
state: self.state,
|
||||
assertion_handler: Some(assertion_handler),
|
||||
message_handler: self.message_handler,
|
||||
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
|
||||
Fm1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult,
|
||||
Fm1: 'static + Send + Sync + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||
{
|
||||
DuringEntity {
|
||||
state: self.state,
|
||||
assertion_handler: self.assertion_handler,
|
||||
message_handler: Some(message_handler),
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
E: 'static + Send + Sync,
|
||||
Fa: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> DuringResult<E>,
|
||||
Fm: 'static + Send + Sync + FnMut(&mut E, &mut Activation, _Any) -> ActorResult,
|
||||
{
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
pub fn create_cap(self, ac: &mut Actor) -> Arc<Cap>
|
||||
{
|
||||
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 {
|
||||
Some(handler) => match handler(&mut self.state, t, a)? {
|
||||
Some(f) => self.during.await_retraction(h, f),
|
||||
|
@ -130,7 +136,7 @@ where
|
|||
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 {
|
||||
Some(handler) => handler(&mut self.state, t, m),
|
||||
None => Ok(()),
|
||||
|
|
|
@ -16,7 +16,7 @@ impl std::fmt::Display for Error {
|
|||
pub fn error<Detail>(message: &str, detail: Detail) -> Error where _Any: From<Detail> {
|
||||
Error {
|
||||
message: message.to_owned(),
|
||||
detail: detail.into(),
|
||||
detail: _Any::from(detail),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,3 @@ static NEXT_HANDLE: AtomicU64 = AtomicU64::new(3);
|
|||
pub fn next_handle() -> Handle {
|
||||
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)
|
||||
}
|
||||
|
|
277
src/relay.rs
277
src/relay.rs
|
@ -8,7 +8,6 @@ use crate::error::error;
|
|||
use crate::schemas::gatekeeper;
|
||||
use crate::schemas::internal_protocol as P;
|
||||
use crate::schemas::sturdy;
|
||||
use crate::schemas::tunnel_relay;
|
||||
|
||||
use futures::Sink;
|
||||
use futures::SinkExt;
|
||||
|
@ -34,7 +33,6 @@ use preserves::value::signed_integer::SignedInteger;
|
|||
use preserves_schema::support::Deserialize;
|
||||
use preserves_schema::support::ParseError;
|
||||
|
||||
use std::any::Any;
|
||||
use std::convert::TryFrom;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
@ -49,15 +47,28 @@ use tokio::io::AsyncWriteExt;
|
|||
|
||||
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 {
|
||||
oid: sturdy::Oid,
|
||||
obj: Arc<Ref>,
|
||||
obj: Arc<Cap>,
|
||||
ref_count: AtomicUsize,
|
||||
}
|
||||
|
||||
struct Membrane {
|
||||
oid_map: Map<sturdy::Oid, Arc<WireSymbol>>,
|
||||
ref_map: Map<Arc<Ref>, Arc<WireSymbol>>,
|
||||
ref_map: Map<Arc<Cap>, Arc<WireSymbol>>,
|
||||
}
|
||||
|
||||
struct Membranes {
|
||||
|
@ -76,10 +87,12 @@ pub enum Output {
|
|||
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.
|
||||
pub struct TunnelRelay
|
||||
{
|
||||
self_ref: Arc<Ref>,
|
||||
self_ref: TunnelRelayRef,
|
||||
input_buffer: BytesMut,
|
||||
inbound_assertions: Map</* remote */ P::Handle, (/* local */ Handle, Vec<Arc<WireSymbol>>)>,
|
||||
outbound_assertions: Map<P::Handle, Vec<Arc<WireSymbol>>>,
|
||||
|
@ -89,7 +102,7 @@ pub struct TunnelRelay
|
|||
}
|
||||
|
||||
struct RelayEntity {
|
||||
relay_ref: Arc<Ref>,
|
||||
relay_ref: TunnelRelayRef,
|
||||
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 {
|
||||
oid: oid.clone(),
|
||||
obj: Arc::clone(&obj),
|
||||
|
@ -124,7 +137,7 @@ impl Membrane {
|
|||
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");
|
||||
ws.acquire();
|
||||
Arc::clone(ws)
|
||||
|
@ -149,18 +162,18 @@ pub fn connect_stream<I, O, E, F>(
|
|||
I: 'static + Send + AsyncRead,
|
||||
O: 'static + Send + AsyncWrite,
|
||||
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 o = Output::Bytes(Box::pin(o));
|
||||
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()?;
|
||||
f(state, t, Arc::clone(denotation))
|
||||
}));
|
||||
t.assert(&gatekeeper, &gatekeeper::Resolve {
|
||||
gatekeeper.assert(t, &gatekeeper::Resolve {
|
||||
sturdyref,
|
||||
observer: main_entity,
|
||||
observer: Cap::new(&main_entity),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -169,12 +182,12 @@ impl TunnelRelay {
|
|||
t: &mut Activation,
|
||||
i: Input,
|
||||
o: Output,
|
||||
initial_ref: Option<Arc<Ref>>,
|
||||
initial_ref: Option<Arc<Cap>>,
|
||||
initial_oid: Option<sturdy::Oid>,
|
||||
) -> Option<Arc<Ref>> {
|
||||
) -> Option<Arc<Cap>> {
|
||||
let (output_tx, output_rx) = unbounded_channel();
|
||||
let mut tr = TunnelRelay {
|
||||
self_ref: Arc::clone(&*INERT_REF), /* placeholder */
|
||||
self_ref: t.actor.create_inert(),
|
||||
input_buffer: BytesMut::with_capacity(1024),
|
||||
output: output_tx,
|
||||
inbound_assertions: Map::new(),
|
||||
|
@ -189,13 +202,10 @@ impl TunnelRelay {
|
|||
if let Some(ir) = initial_ref {
|
||||
tr.membranes.export_ref(ir, true);
|
||||
}
|
||||
let mut result = None;
|
||||
let tr_ref = t.actor.create_rec(tr, |ac, tr, tr_ref| {
|
||||
tr.self_ref = Arc::clone(tr_ref);
|
||||
if let Some(io) = initial_oid {
|
||||
result = Some(Arc::clone(&tr.membranes.import_oid(ac, tr_ref, io).obj));
|
||||
}
|
||||
});
|
||||
let result = initial_oid.map(
|
||||
|io| Arc::clone(&tr.membranes.import_oid(t.actor, &tr.self_ref, io).obj));
|
||||
let tr_ref = Arc::clone(&tr.self_ref);
|
||||
tr_ref.become_entity(tr);
|
||||
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!("reader"), input_loop(i, tr_ref));
|
||||
|
@ -228,9 +238,10 @@ impl TunnelRelay {
|
|||
a.foreach_embedded::<_, Error>(&mut |r| {
|
||||
Ok(imported.push(imported_membrane.acquire(r)))
|
||||
})?;
|
||||
let local_handle = t.assert(target, a);
|
||||
if let Some(_) = self.inbound_assertions.insert(remote_handle, (local_handle, imported)) {
|
||||
return Err(error("Assertion with duplicate handle", _Any::new(false)));
|
||||
if let Some(local_handle) = target.assert(t, a) {
|
||||
if let Some(_) = self.inbound_assertions.insert(remote_handle, (local_handle, imported)) {
|
||||
return Err(error("Assertion with duplicate handle", _Any::new(false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
P::Event::Retract(b) => {
|
||||
|
@ -254,26 +265,20 @@ impl TunnelRelay {
|
|||
_ => Ok(())
|
||||
}
|
||||
})?;
|
||||
t.message(target, a);
|
||||
target.message(t, a);
|
||||
}
|
||||
P::Event::Sync(b) => {
|
||||
let P::Sync { peer } = *b;
|
||||
self.membranes.imported.acquire(&peer);
|
||||
struct SyncPeer {
|
||||
tr: Arc<Ref>,
|
||||
peer: Arc<Ref>,
|
||||
tr: TunnelRelayRef,
|
||||
peer: Arc<Cap>,
|
||||
}
|
||||
impl Entity for SyncPeer {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn message(&mut self, t: &mut Activation, a: _Any) -> ActorResult {
|
||||
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)
|
||||
});
|
||||
}
|
||||
impl Entity<Synced> for SyncPeer {
|
||||
fn message(&mut self, t: &mut Activation, _a: Synced) -> ActorResult {
|
||||
self.peer.message(t, _Any::new(true));
|
||||
t.message(&self.tr, RelayProtocol::SyncGc(
|
||||
Arc::clone(&self.peer)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -281,7 +286,7 @@ impl TunnelRelay {
|
|||
tr: Arc::clone(&self.self_ref),
|
||||
peer: Arc::clone(&peer),
|
||||
});
|
||||
t.sync(&peer, k);
|
||||
t.sync(&peer.underlying, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +341,7 @@ impl TunnelRelay {
|
|||
}
|
||||
|
||||
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) {
|
||||
None => {
|
||||
let oid = sturdy::Oid(SignedInteger::from(self.next_export_oid as u128));
|
||||
|
@ -354,17 +359,17 @@ impl Membranes {
|
|||
fn import_oid(
|
||||
&mut self,
|
||||
ac: &mut Actor,
|
||||
relay_ref: &Arc<Ref>,
|
||||
relay_ref: &TunnelRelayRef,
|
||||
oid: sturdy::Oid,
|
||||
) -> Arc<WireSymbol> {
|
||||
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>>(
|
||||
&mut self,
|
||||
t: &mut Activation,
|
||||
relay_ref: &Arc<Ref>,
|
||||
relay_ref: &TunnelRelayRef,
|
||||
src: &'src mut S,
|
||||
_read_annotations: bool,
|
||||
) -> 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>,
|
||||
&'m Arc<Ref>,
|
||||
&'m TunnelRelayRef,
|
||||
&'m mut Membranes);
|
||||
|
||||
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,
|
||||
relay: Arc<Ref>,
|
||||
relay: TunnelRelayRef,
|
||||
) -> ActorResult {
|
||||
#[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;
|
||||
let m = m.into();
|
||||
let relay = Arc::clone(relay);
|
||||
external_event(&Arc::clone(&relay), debtor, Box::new(
|
||||
move |t| relay.with_entity(|e| e.message(t, m))))
|
||||
external_event(&Arc::clone(&relay.mailbox), debtor, Box::new(
|
||||
move |t| relay.with_entity(|e| e.message(t, RelayProtocol::Input(m)))))
|
||||
}
|
||||
|
||||
let debtor = Debtor::new(crate::name!("input-loop"));
|
||||
|
@ -468,11 +476,11 @@ pub async fn input_loop(
|
|||
loop {
|
||||
match src.next().await {
|
||||
None => {
|
||||
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?;
|
||||
s(&relay, &debtor, RelayInput::Eof).await?;
|
||||
return Ok(());
|
||||
}
|
||||
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,
|
||||
Err(e) =>
|
||||
if e.kind() == io::ErrorKind::ConnectionReset {
|
||||
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?;
|
||||
s(&relay, &debtor, RelayInput::Eof).await?;
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(e)?;
|
||||
|
@ -494,14 +502,14 @@ pub async fn input_loop(
|
|||
};
|
||||
match n {
|
||||
0 => {
|
||||
s(&relay, &debtor, &tunnel_relay::Input::Eof).await?;
|
||||
s(&relay, &debtor, RelayInput::Eof).await?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {
|
||||
while buf.has_remaining() {
|
||||
let bs = buf.chunk();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -511,7 +519,7 @@ pub async fn input_loop(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn output_loop(
|
||||
async fn output_loop(
|
||||
mut o: Output,
|
||||
mut output_rx: UnboundedReceiver<LoanedItem<Vec<u8>>>,
|
||||
) -> ActorResult {
|
||||
|
@ -532,81 +540,69 @@ pub async fn output_loop(
|
|||
}
|
||||
}
|
||||
|
||||
impl Entity for TunnelRelay {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||
if let Ok(m) = tunnel_relay::RelayProtocol::try_from(&m) {
|
||||
match m {
|
||||
tunnel_relay::RelayProtocol::Input(b) => match *b {
|
||||
tunnel_relay::Input::Eof => {
|
||||
t.actor.shutdown();
|
||||
}
|
||||
tunnel_relay::Input::Packet { bs } => {
|
||||
let mut src = BytesBinarySource::new(&bs);
|
||||
impl Entity<RelayProtocol> for TunnelRelay {
|
||||
fn message(&mut self, t: &mut Activation, m: RelayProtocol) -> ActorResult {
|
||||
match m {
|
||||
RelayProtocol::Input(RelayInput::Eof) => {
|
||||
t.actor.shutdown();
|
||||
}
|
||||
RelayProtocol::Input(RelayInput::Packet(bs)) => {
|
||||
let mut src = BytesBinarySource::new(&bs);
|
||||
let mut dec = ActivatedMembranes(t, &self.self_ref, &mut self.membranes);
|
||||
let mut r = src.packed::<_, _Any, _>(&mut dec);
|
||||
let item = P::Packet::deserialize(&mut r)?;
|
||||
self.handle_inbound_packet(t, item)?;
|
||||
}
|
||||
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 r = src.packed::<_, _Any, _>(&mut dec);
|
||||
let item = P::Packet::deserialize(&mut r)?;
|
||||
self.handle_inbound_packet(t, item)?;
|
||||
}
|
||||
tunnel_relay::Input::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 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)?,
|
||||
let e = match P::Packet::deserialize(&mut r) {
|
||||
Err(ParseError::Preserves(PreservesError::Io(e)))
|
||||
if is_eof_io_error(&e) =>
|
||||
None,
|
||||
result => Some(result?),
|
||||
};
|
||||
self.pending_outbound.push(turn_event);
|
||||
}
|
||||
}
|
||||
tunnel_relay::RelayProtocol::SyncGc(b) => match *b {
|
||||
tunnel_relay::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);
|
||||
(e, r.source.index)
|
||||
};
|
||||
match e {
|
||||
None => break,
|
||||
Some(item) => {
|
||||
self.input_buffer.advance(count);
|
||||
self.handle_inbound_packet(t, item)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
tunnel_relay::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))))?
|
||||
}
|
||||
RelayProtocol::Output(oid, event) => {
|
||||
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(())
|
||||
}
|
||||
|
||||
fn exit_hook(&mut self, t: &mut Activation, exit_status: &ActorResult) -> ActorResult {
|
||||
if let Err(e) = exit_status {
|
||||
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
||||
if let Err(e) = &**exit_status {
|
||||
let e = e.clone();
|
||||
self.send_packet(&t.debtor, 1, P::Packet::Error(Box::new(e)))?;
|
||||
}
|
||||
|
@ -614,37 +610,30 @@ impl Entity for TunnelRelay {
|
|||
}
|
||||
}
|
||||
|
||||
impl Entity for RelayEntity {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
impl Entity<_Any> for RelayEntity {
|
||||
fn assert(&mut self, t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: P::Event::Assert(Box::new(P::Assert {
|
||||
Ok(t.message(&self.relay_ref, RelayProtocol::Output(
|
||||
self.oid.clone(),
|
||||
P::Event::Assert(Box::new(P::Assert {
|
||||
assertion: P::Assertion(a),
|
||||
handle: P::Handle(h.into()),
|
||||
})),
|
||||
}))
|
||||
})))))
|
||||
}
|
||||
fn retract(&mut self, t: &mut Activation, h: Handle) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: P::Event::Retract(Box::new(P::Retract {
|
||||
Ok(t.message(&self.relay_ref, RelayProtocol::Output(
|
||||
self.oid.clone(),
|
||||
P::Event::Retract(Box::new(P::Retract {
|
||||
handle: P::Handle(h.into()),
|
||||
})),
|
||||
}))
|
||||
})))))
|
||||
}
|
||||
fn message(&mut self, t: &mut Activation, m: _Any) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: P::Event::Message(Box::new(P::Message { body: P::Assertion(m) })),
|
||||
}))
|
||||
Ok(t.message(&self.relay_ref, RelayProtocol::Output(
|
||||
self.oid.clone(),
|
||||
P::Event::Message(Box::new(P::Message { body: P::Assertion(m) })))))
|
||||
}
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref>) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, &tunnel_relay::Output {
|
||||
oid: self.oid.clone(),
|
||||
event: P::Event::Sync(Box::new(P::Sync { peer })),
|
||||
}))
|
||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
|
||||
Ok(t.message(&self.relay_ref, RelayProtocol::Output(
|
||||
self.oid.clone(),
|
||||
P::Event::Sync(Box::new(P::Sync { peer: Cap::guard(&peer) })))))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
@ -9,7 +9,7 @@ use std::sync::Arc;
|
|||
use crate::actor::_Any;
|
||||
use crate::actor::Activation;
|
||||
use crate::actor::Handle;
|
||||
use crate::actor::Ref;
|
||||
use crate::actor::Cap;
|
||||
use crate::schemas::dataspace_patterns as ds;
|
||||
use crate::pattern::{self, PathStep, Path, Paths};
|
||||
|
||||
|
@ -58,7 +58,7 @@ struct Leaf { // aka Topic
|
|||
#[derive(Debug)]
|
||||
struct Endpoints {
|
||||
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,
|
||||
t: &mut Activation,
|
||||
pat: &ds::Pattern,
|
||||
observer: &Arc<Ref>,
|
||||
observer: &Arc<Cap>,
|
||||
) {
|
||||
let analysis = pattern::PatternAnalysis::new(pat);
|
||||
self.root.extend(pat).add_observer(t, &analysis, observer);
|
||||
|
@ -87,7 +87,7 @@ impl Index {
|
|||
&mut self,
|
||||
t: &mut Activation,
|
||||
pat: ds::Pattern,
|
||||
observer: &Arc<Ref>,
|
||||
observer: &Arc<Cap>,
|
||||
) {
|
||||
let analysis = pattern::PatternAnalysis::new(&pat);
|
||||
self.root.extend(&pat).remove_observer(t, analysis, observer);
|
||||
|
@ -106,7 +106,9 @@ impl Index {
|
|||
|es, cs| {
|
||||
if es.cached_captures.change(cs.clone(), 1) == bag::Net::AbsentToPresent {
|
||||
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| {
|
||||
*delivery_count += es.endpoints.len();
|
||||
for observer in es.endpoints.keys() {
|
||||
t.message(observer, cs.clone());
|
||||
observer.message(t, cs.clone());
|
||||
}
|
||||
}).perform(&mut self.root);
|
||||
}
|
||||
|
@ -389,7 +391,7 @@ impl Continuation {
|
|||
&mut self,
|
||||
t: &mut Activation,
|
||||
analysis: &pattern::PatternAnalysis,
|
||||
observer: &Arc<Ref>,
|
||||
observer: &Arc<Cap>,
|
||||
) {
|
||||
let cached_assertions = &self.cached_assertions;
|
||||
let const_val_map =
|
||||
|
@ -418,7 +420,9 @@ impl Continuation {
|
|||
});
|
||||
let mut capture_map = Map::new();
|
||||
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);
|
||||
}
|
||||
|
@ -427,7 +431,7 @@ impl Continuation {
|
|||
&mut self,
|
||||
t: &mut Activation,
|
||||
analysis: pattern::PatternAnalysis,
|
||||
observer: &Arc<Ref>,
|
||||
observer: &Arc<Cap>,
|
||||
) {
|
||||
if let Entry::Occupied(mut const_val_map_entry)
|
||||
= self.leaf_map.entry(analysis.const_paths)
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
use crate::actor::*;
|
||||
|
||||
use preserves::value::NestedValue;
|
||||
|
||||
use std::any::Any;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Tracer(tracing::Span);
|
||||
|
||||
fn set_name_oid(_ac: &mut Actor, t: &mut Tracer, r: &Arc<Ref>) {
|
||||
t.0.record("oid", &tracing::field::display(&r.addr.oid()));
|
||||
fn set_name_oid<M>(t: &mut Tracer, r: &Arc<Ref<M>>) {
|
||||
t.0.record("oid", &tracing::field::display(&r.oid()));
|
||||
}
|
||||
|
||||
pub fn tracer(ac: &mut Actor, name: tracing::Span) -> Arc<Ref> {
|
||||
ac.create_rec(Tracer(name), set_name_oid)
|
||||
pub fn tracer<M: Debug>(ac: &mut Actor, name: tracing::Span) -> Arc<Ref<M>> {
|
||||
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> {
|
||||
Actor::create_and_start_rec(crate::name!(parent: None, "tracer"), Tracer(name), set_name_oid)
|
||||
pub fn tracer_top<M: Debug>(name: tracing::Span) -> Arc<Ref<M>> {
|
||||
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 {
|
||||
fn as_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn assert(&mut self, _t: &mut Activation, a: _Any, h: Handle) -> ActorResult {
|
||||
impl<M: Debug> Entity<M> for Tracer {
|
||||
fn assert(&mut self, _t: &mut Activation, a: M, h: Handle) -> ActorResult {
|
||||
let _guard = self.0.enter();
|
||||
tracing::trace!(a = debug(&a), h = debug(&h), "assert");
|
||||
Ok(())
|
||||
|
@ -33,15 +36,15 @@ impl Entity for Tracer {
|
|||
tracing::trace!(h = debug(&h), "retract");
|
||||
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();
|
||||
tracing::trace!(m = debug(&m), "message");
|
||||
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();
|
||||
tracing::trace!(peer = debug(&peer), "sync");
|
||||
t.message(&peer, _Any::new(true));
|
||||
t.message(&peer, Synced);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue