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 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(())
|
||||||
|
|
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());
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)))))?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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(())
|
||||||
});
|
});
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)))))?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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::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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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(()),
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
277
src/relay.rs
277
src/relay.rs
|
@ -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) })))))
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue