Actions as closures rather than data
This commit is contained in:
parent
21a69618cf
commit
4a69d5573f
|
@ -11,7 +11,6 @@ use syndicate::actor::*;
|
||||||
use syndicate::dataspace::Dataspace;
|
use syndicate::dataspace::Dataspace;
|
||||||
use syndicate::schemas::dataspace::Observe;
|
use syndicate::schemas::dataspace::Observe;
|
||||||
use syndicate::schemas::dataspace_patterns as p;
|
use syndicate::schemas::dataspace_patterns as p;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
use syndicate::value::Value;
|
use syndicate::value::Value;
|
||||||
|
@ -63,14 +62,15 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
let debtor = Debtor::new(syndicate::name!("sender-debtor"));
|
let debtor = Debtor::new(syndicate::name!("sender-debtor"));
|
||||||
ac.linked_task(syndicate::name!("sender"), async move {
|
ac.linked_task(syndicate::name!("sender"), async move {
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
external_event(&ds, &debtor, Event::Message(Box::new(Message {
|
let ds = Arc::clone(&ds);
|
||||||
body: Assertion(says(_Any::new("bench_pub"),
|
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||||
Value::ByteString(vec![]).wrap())),
|
move |t| ds.with_entity(
|
||||||
}))).await?
|
|e| e.message(t, says(_Any::new("bench_pub"),
|
||||||
|
Value::ByteString(vec![]).wrap())))))?
|
||||||
}
|
}
|
||||||
external_event(&shutdown, &debtor, Event::Message(Box::new(Message {
|
external_event(&Arc::clone(&shutdown), &debtor, Box::new(
|
||||||
body: Assertion(_Any::new(true)),
|
move |t| shutdown.with_entity(
|
||||||
}))).await?;
|
|e| e.message(t, _Any::new(true)))))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
ac.start(syndicate::name!("dataspace")).await.unwrap().unwrap();
|
ac.start(syndicate::name!("dataspace")).await.unwrap().unwrap();
|
||||||
|
@ -134,14 +134,18 @@ pub fn bench_pub(c: &mut Criterion) {
|
||||||
let debtor = t.debtor.clone();
|
let debtor = t.debtor.clone();
|
||||||
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 {
|
||||||
external_event(&ds, &debtor, Event::Message(Box::new(Message {
|
let ds = Arc::clone(&ds);
|
||||||
body: Assertion(says(_Any::new("bench_pub"),
|
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||||
Value::ByteString(vec![]).wrap())),
|
move |t| ds.with_entity(
|
||||||
}))).await?
|
|e| e.message(t, says(_Any::new("bench_pub"),
|
||||||
|
Value::ByteString(vec![]).wrap())))))?
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let ds = Arc::clone(&ds);
|
||||||
|
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||||
|
move |t| ds.with_entity(
|
||||||
|
|e| e.message(t, _Any::new(true)))))?;
|
||||||
}
|
}
|
||||||
external_event(&ds, &debtor, Event::Message(Box::new(Message {
|
|
||||||
body: Assertion(_Any::new(true)),
|
|
||||||
}))).await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -7,7 +7,6 @@ use syndicate::actor::*;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::dataspace::Observe;
|
use syndicate::schemas::dataspace::Observe;
|
||||||
use syndicate::schemas::dataspace_patterns as p;
|
use syndicate::schemas::dataspace_patterns as p;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
@ -68,11 +67,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
external_event(&consumer,
|
let consumer = Arc::clone(&consumer);
|
||||||
|
external_event(&Arc::clone(&consumer),
|
||||||
&Debtor::new(syndicate::name!("debtor")),
|
&Debtor::new(syndicate::name!("debtor")),
|
||||||
Event::Message(Box::new(Message {
|
Box::new(move |t| consumer.with_entity(
|
||||||
body: Assertion(_Any::new(true)),
|
|e| e.message(t, _Any::new(true)))))?;
|
||||||
}))).await?;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -8,7 +8,6 @@ use syndicate::actor::*;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::dataspace::Observe;
|
use syndicate::schemas::dataspace::Observe;
|
||||||
use syndicate::schemas::dataspace_patterns as p;
|
use syndicate::schemas::dataspace_patterns as p;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
@ -190,11 +189,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
external_event(&consumer,
|
let consumer = Arc::clone(&consumer);
|
||||||
|
external_event(&Arc::clone(&consumer),
|
||||||
&Debtor::new(syndicate::name!("debtor")),
|
&Debtor::new(syndicate::name!("debtor")),
|
||||||
Event::Message(Box::new(Message {
|
Box::new(move |t| consumer.with_entity(
|
||||||
body: Assertion(_Any::new(true)),
|
|e| e.message(t, _Any::new(true)))))?;
|
||||||
}))).await?;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -205,16 +204,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
t.actor.linked_task(syndicate::name!("boot-ping"), async move {
|
t.actor.linked_task(syndicate::name!("boot-ping"), async move {
|
||||||
let padding: _Any = Value::ByteString(vec![0; bytes_padding]).wrap();
|
let padding: _Any = Value::ByteString(vec![0; bytes_padding]).wrap();
|
||||||
for _ in 0..turn_count {
|
for _ in 0..turn_count {
|
||||||
let mut events = vec![];
|
let mut events: PendingEventQueue = vec![];
|
||||||
let current_rec = simple_record2(send_label,
|
let current_rec = simple_record2(send_label,
|
||||||
Value::from(now()).wrap(),
|
Value::from(now()).wrap(),
|
||||||
padding.clone());
|
padding.clone());
|
||||||
for _ in 0..action_count {
|
for _ in 0..action_count {
|
||||||
events.push((ds.clone(), Event::Message(Box::new(Message {
|
let ds = Arc::clone(&ds);
|
||||||
body: Assertion(current_rec.clone()),
|
let current_rec = current_rec.clone();
|
||||||
}))));
|
events.push(Box::new(move |t| ds.with_entity(
|
||||||
|
|e| e.message(t, current_rec))));
|
||||||
}
|
}
|
||||||
external_events(&ds, &debtor, events).await?
|
external_events(&ds, &debtor, events)?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Value;
|
use syndicate::value::Value;
|
||||||
|
|
||||||
|
@ -43,13 +44,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
t.actor.linked_task(syndicate::name!("sender"), async move {
|
t.actor.linked_task(syndicate::name!("sender"), async move {
|
||||||
loop {
|
loop {
|
||||||
debtor.ensure_clear_funds().await;
|
debtor.ensure_clear_funds().await;
|
||||||
let mut events = Vec::new();
|
let mut events: PendingEventQueue = Vec::new();
|
||||||
for _ in 0..action_count {
|
for _ in 0..action_count {
|
||||||
events.push((ds.clone(), Event::Message(Box::new(Message {
|
let ds = Arc::clone(&ds);
|
||||||
body: Assertion(says(Value::from("producer").wrap(), padding.clone())),
|
let padding = padding.clone();
|
||||||
}))));
|
events.push(Box::new(move |t| ds.with_entity(
|
||||||
|
|e| e.message(t, says(Value::from("producer").wrap(), padding)))));
|
||||||
}
|
}
|
||||||
external_events(&ds, &debtor, events).await?;
|
external_events(&ds, &debtor, events)?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -7,7 +7,6 @@ use syndicate::actor::*;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::dataspace::Observe;
|
use syndicate::schemas::dataspace::Observe;
|
||||||
use syndicate::schemas::dataspace_patterns as p;
|
use syndicate::schemas::dataspace_patterns as p;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Map;
|
use syndicate::value::Map;
|
||||||
use syndicate::value::NestedValue;
|
use syndicate::value::NestedValue;
|
||||||
|
@ -84,11 +83,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut stats_timer = interval(Duration::from_secs(1));
|
let mut stats_timer = interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
stats_timer.tick().await;
|
stats_timer.tick().await;
|
||||||
external_event(&consumer,
|
let consumer = Arc::clone(&consumer);
|
||||||
|
external_event(&Arc::clone(&consumer),
|
||||||
&Debtor::new(syndicate::name!("debtor")),
|
&Debtor::new(syndicate::name!("debtor")),
|
||||||
Event::Message(Box::new(Message {
|
Box::new(move |t| consumer.with_entity(
|
||||||
body: Assertion(_Any::new(true)),
|
|e| e.message(t, _Any::new(true)))))?;
|
||||||
}))).await?;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use syndicate::actor::*;
|
use syndicate::actor::*;
|
||||||
use syndicate::relay;
|
use syndicate::relay;
|
||||||
use syndicate::schemas::internal_protocol::*;
|
|
||||||
use syndicate::sturdy;
|
use syndicate::sturdy;
|
||||||
use syndicate::value::Value;
|
use syndicate::value::Value;
|
||||||
|
|
||||||
|
@ -28,18 +29,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
"Present",
|
"Present",
|
||||||
Value::from(std::process::id()).wrap()).wrap();
|
Value::from(std::process::id()).wrap()).wrap();
|
||||||
let handle = syndicate::next_handle();
|
let handle = syndicate::next_handle();
|
||||||
let assert_e = Event::Assert(Box::new(Assert {
|
let assert_e = || {
|
||||||
assertion: Assertion(presence),
|
let ds = Arc::clone(&ds);
|
||||||
handle: handle.clone(),
|
let presence = presence.clone();
|
||||||
}));
|
let handle = handle.clone();
|
||||||
let retract_e = Event::Retract(Box::new(Retract {
|
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||||
handle,
|
move |t| ds.with_entity(|e| e.assert(t, presence, handle))))
|
||||||
}));
|
};
|
||||||
external_event(&ds, &debtor, assert_e.clone()).await?;
|
let retract_e = || {
|
||||||
|
let ds = Arc::clone(&ds);
|
||||||
|
let handle = handle.clone();
|
||||||
|
external_event(&Arc::clone(&ds), &debtor, Box::new(
|
||||||
|
move |t| ds.with_entity(|e| e.retract(t, handle))))
|
||||||
|
};
|
||||||
|
assert_e()?;
|
||||||
loop {
|
loop {
|
||||||
debtor.ensure_clear_funds().await;
|
debtor.ensure_clear_funds().await;
|
||||||
external_event(&ds, &debtor, retract_e.clone()).await?;
|
retract_e()?;
|
||||||
external_event(&ds, &debtor, assert_e.clone()).await?;
|
assert_e()?;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
150
src/actor.rs
150
src/actor.rs
|
@ -3,7 +3,6 @@ pub use futures::future::BoxFuture;
|
||||||
pub use std::future::ready;
|
pub use std::future::ready;
|
||||||
|
|
||||||
use super::ActorId;
|
use super::ActorId;
|
||||||
use super::schemas::internal_protocol::*;
|
|
||||||
use super::schemas::sturdy;
|
use super::schemas::sturdy;
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
use super::error::error;
|
use super::error::error;
|
||||||
|
@ -25,7 +24,6 @@ use std::sync::atomic::{AtomicI64, AtomicU64, AtomicUsize, Ordering};
|
||||||
|
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender, UnboundedReceiver};
|
||||||
// use tokio::sync::Notify;
|
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
@ -61,19 +59,20 @@ pub trait Entity: Send + std::marker::Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Destination {
|
enum Destination {
|
||||||
ImmediateSelf(Arc<Ref>),
|
ImmediateSelf(Action),
|
||||||
Remote(Arc<Ref>),
|
Remote(Arc<Ref>, Action),
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutboundAssertions = Map<Handle, Destination>;
|
type OutboundAssertions = Map<Handle, Destination>;
|
||||||
type PendingEventQueue = Vec<(Arc<Ref>, Event)>;
|
pub type Action = Box<dyn Send + Sync + FnOnce(&mut Activation) -> ActorResult>;
|
||||||
|
pub type PendingEventQueue = Vec<Action>;
|
||||||
|
|
||||||
// This is what other implementations call a "Turn", renamed here to
|
// This is what other implementations call a "Turn", renamed here to
|
||||||
// avoid conflicts with schemas::internal_protocol::Turn.
|
// avoid conflicts with schemas::internal_protocol::Turn.
|
||||||
pub struct Activation<'activation> {
|
pub struct Activation<'activation> {
|
||||||
pub actor: &'activation mut Actor,
|
pub actor: &'activation mut Actor,
|
||||||
pub debtor: Arc<Debtor>,
|
pub debtor: Arc<Debtor>,
|
||||||
queues: HashMap<ActorId, PendingEventQueue>,
|
queues: HashMap<ActorId, (UnboundedSender<SystemMessage>, PendingEventQueue)>,
|
||||||
immediate_self: PendingEventQueue,
|
immediate_self: PendingEventQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +90,6 @@ pub struct LoanedItem<T> {
|
||||||
pub item: T,
|
pub item: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum SystemMessage {
|
enum SystemMessage {
|
||||||
Release,
|
Release,
|
||||||
Turn(LoanedItem<PendingEventQueue>),
|
Turn(LoanedItem<PendingEventQueue>),
|
||||||
|
@ -225,9 +223,20 @@ impl<'activation> Activation<'activation> {
|
||||||
pub fn assert<M>(&mut self, r: &Arc<Ref>, a: M) -> Handle where M: Into<_Any> {
|
pub fn assert<M>(&mut self, r: &Arc<Ref>, a: M) -> Handle where M: Into<_Any> {
|
||||||
let handle = crate::next_handle();
|
let handle = crate::next_handle();
|
||||||
if let Some(assertion) = r.rewrite(a.into()) {
|
if let Some(assertion) = r.rewrite(a.into()) {
|
||||||
self.queue_for(r).push((Arc::clone(r), Event::Assert(Box::new(
|
{
|
||||||
Assert { assertion, handle: handle.clone() }))));
|
let r = Arc::clone(r);
|
||||||
self.actor.outbound_assertions.insert(handle.clone(), Destination::Remote(Arc::clone(r)));
|
let handle = handle.clone();
|
||||||
|
self.queue_for(&r).push(Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.assert(t, assertion, handle))));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let r = Arc::clone(r);
|
||||||
|
let handle = handle.clone();
|
||||||
|
self.actor.outbound_assertions.insert(
|
||||||
|
handle.clone(),
|
||||||
|
Destination::Remote(Arc::clone(&r), Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.retract(t, handle)))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
@ -236,59 +245,73 @@ impl<'activation> Activation<'activation> {
|
||||||
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()) {
|
if let Some(assertion) = r.rewrite(a.into()) {
|
||||||
self.immediate_self.push((r.clone(), Event::Assert(Box::new(
|
{
|
||||||
Assert { assertion, handle: handle.clone() }))));
|
let r = Arc::clone(r);
|
||||||
self.actor.outbound_assertions.insert(handle.clone(), Destination::ImmediateSelf(r.clone()));
|
let handle = handle.clone();
|
||||||
|
self.immediate_self.push(Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.assert(t, assertion, handle))));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let r = Arc::clone(r);
|
||||||
|
let handle = handle.clone();
|
||||||
|
self.actor.outbound_assertions.insert(
|
||||||
|
handle.clone(),
|
||||||
|
Destination::ImmediateSelf(Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.retract(t, handle)))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retract(&mut self, handle: Handle) {
|
pub fn retract(&mut self, handle: Handle) {
|
||||||
if let Some(d) = self.actor.outbound_assertions.remove(&handle) {
|
if let Some(d) = self.actor.outbound_assertions.remove(&handle) {
|
||||||
self.retract_known_ref(d, handle)
|
self.retract_known_ref(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retract_known_ref(&mut self, d: Destination, handle: Handle) {
|
fn retract_known_ref(&mut self, d: Destination) {
|
||||||
match d {
|
match d {
|
||||||
Destination::Remote(r) =>
|
Destination::Remote(r, action) =>
|
||||||
self.queue_for(&r).push((r, Event::Retract(Box::new(Retract { handle })))),
|
self.queue_for(&r).push(action),
|
||||||
Destination::ImmediateSelf(r) =>
|
Destination::ImmediateSelf(action) =>
|
||||||
self.immediate_self.push((r, Event::Retract(Box::new(Retract { handle })))),
|
self.immediate_self.push(action),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> {
|
pub fn message<M>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> {
|
||||||
if let Some(body) = r.rewrite(m.into()) {
|
if let Some(body) = r.rewrite(m.into()) {
|
||||||
self.queue_for(r).push((Arc::clone(r), Event::Message(Box::new(
|
let r = Arc::clone(r);
|
||||||
Message { body }))))
|
self.queue_for(&r).push(Box::new(
|
||||||
|
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>(&mut self, r: &Arc<Ref>, m: M) where M: Into<_Any> {
|
||||||
self.immediate_oid(r);
|
self.immediate_oid(r);
|
||||||
if let Some(body) = r.rewrite(m.into()) {
|
if let Some(body) = r.rewrite(m.into()) {
|
||||||
self.immediate_self.push((r.clone(), Event::Message(Box::new(Message { body }))));
|
let r = Arc::clone(r);
|
||||||
|
self.immediate_self.push(Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.message(t, body))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync(&mut self, r: &Arc<Ref>, peer: Arc<Ref>) {
|
pub fn sync(&mut self, r: &Arc<Ref>, peer: Arc<Ref>) {
|
||||||
self.queue_for(r).push((Arc::clone(r), Event::Sync(Box::new(Sync { peer }))));
|
let r = Arc::clone(r);
|
||||||
|
self.queue_for(&r).push(Box::new(
|
||||||
|
move |t| r.with_entity(|e| e.sync(t, peer))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut PendingEventQueue {
|
fn queue_for(&mut self, r: &Arc<Ref>) -> &mut PendingEventQueue {
|
||||||
self.queues.entry(r.addr.mailbox.actor_id).or_default()
|
&mut self.queues.entry(r.addr.mailbox.actor_id)
|
||||||
|
.or_insert((r.addr.mailbox.tx.clone(), Vec::new())).1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deliver(&mut self) {
|
fn deliver(&mut self) {
|
||||||
if !self.immediate_self.is_empty() {
|
if !self.immediate_self.is_empty() {
|
||||||
panic!("Unprocessed immediate_self events remain at deliver() time");
|
panic!("Unprocessed immediate_self events remain at deliver() time");
|
||||||
}
|
}
|
||||||
for (_actor_id, turn) in std::mem::take(&mut self.queues).into_iter() {
|
for (_actor_id, (tx, turn)) in std::mem::take(&mut self.queues).into_iter() {
|
||||||
if turn.len() == 0 { continue; }
|
let _ = send_actions(&tx, &self.debtor, turn);
|
||||||
let first_ref = Arc::clone(&turn[0].0);
|
|
||||||
let target = &first_ref.addr.mailbox;
|
|
||||||
let _ = target.send(&self.debtor, turn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,13 +380,15 @@ impl<T> Drop for LoanedItem<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mailbox {
|
#[must_use]
|
||||||
#[must_use]
|
fn send_actions(
|
||||||
pub fn send(&self, debtor: &Arc<Debtor>, t: PendingEventQueue) -> ActorResult {
|
tx: &UnboundedSender<SystemMessage>,
|
||||||
let token_count = t.len();
|
debtor: &Arc<Debtor>,
|
||||||
self.tx.send(SystemMessage::Turn(LoanedItem::new(debtor, token_count, t)))
|
t: PendingEventQueue,
|
||||||
.map_err(|_| error("Target actor not running", _Any::new(false)))
|
) -> ActorResult {
|
||||||
}
|
let token_count = t.len();
|
||||||
|
tx.send(SystemMessage::Turn(LoanedItem::new(debtor, token_count, t)))
|
||||||
|
.map_err(|_| error("Target actor not running", _Any::new(false)))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Mailbox {
|
impl std::fmt::Debug for Mailbox {
|
||||||
|
@ -518,8 +543,7 @@ impl Actor {
|
||||||
{
|
{
|
||||||
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 r in std::mem::take(&mut t.actor.exit_hooks) {
|
||||||
let mut e = r.addr.target.write().expect("unpoisoned");
|
if let Err(err) = r.with_entity(|e| e.exit_hook(&mut t, &result)) {
|
||||||
if let Err(err) = e.exit_hook(&mut t, &result) {
|
|
||||||
tracing::error!(err = debug(err),
|
tracing::error!(err = debug(err),
|
||||||
r = debug(&r),
|
r = debug(&r),
|
||||||
"error in exit hook");
|
"error in exit hook");
|
||||||
|
@ -574,32 +598,12 @@ impl Actor {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
SystemMessage::Turn(mut loaned_item) => {
|
SystemMessage::Turn(mut loaned_item) => {
|
||||||
let mut events = std::mem::take(&mut loaned_item.item);
|
let mut actions = std::mem::take(&mut loaned_item.item);
|
||||||
let mut t = Activation::new(self, Arc::clone(&loaned_item.debtor));
|
let mut t = Activation::new(self, Arc::clone(&loaned_item.debtor));
|
||||||
loop {
|
loop {
|
||||||
for (r, event) in events.into_iter() {
|
for action in actions.into_iter() { action(&mut t)? }
|
||||||
let mut e = r.addr.target.write().expect("unpoisoned");
|
actions = std::mem::take(&mut t.immediate_self);
|
||||||
match event {
|
if actions.is_empty() { break; }
|
||||||
Event::Assert(b) => {
|
|
||||||
let Assert { assertion: Assertion(assertion), handle } = *b;
|
|
||||||
e.assert(&mut t, assertion, handle)?
|
|
||||||
}
|
|
||||||
Event::Retract(b) => {
|
|
||||||
let Retract { handle } = *b;
|
|
||||||
e.retract(&mut t, handle)?
|
|
||||||
}
|
|
||||||
Event::Message(b) => {
|
|
||||||
let Message { body: Assertion(body) } = *b;
|
|
||||||
e.message(&mut t, body)?
|
|
||||||
}
|
|
||||||
Event::Sync(b) => {
|
|
||||||
let Sync { peer } = *b;
|
|
||||||
e.sync(&mut t, peer)?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
events = std::mem::take(&mut t.immediate_self);
|
|
||||||
if events.is_empty() { break; }
|
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
@ -662,9 +666,9 @@ impl Drop for Actor {
|
||||||
let to_clear = std::mem::take(&mut self.outbound_assertions);
|
let to_clear = std::mem::take(&mut self.outbound_assertions);
|
||||||
{
|
{
|
||||||
let mut t = Activation::new(self, Debtor::new(crate::name!("drop")));
|
let mut t = Activation::new(self, Debtor::new(crate::name!("drop")));
|
||||||
for (handle, r) in to_clear.into_iter() {
|
for (_handle, r) in to_clear.into_iter() {
|
||||||
tracing::trace!(h = debug(&handle), "retract on termination");
|
tracing::trace!(h = debug(&_handle), "retract on termination");
|
||||||
t.retract_known_ref(r, handle);
|
t.retract_known_ref(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,16 +677,20 @@ impl Drop for Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub async fn external_event(r: &Arc<Ref>, debtor: &Arc<Debtor>, event: Event) -> ActorResult {
|
pub fn external_event(r: &Arc<Ref>, debtor: &Arc<Debtor>, action: Action) -> ActorResult {
|
||||||
r.addr.mailbox.send(debtor, vec![(r.clone(), event)])
|
send_actions(&r.addr.mailbox.tx, debtor, vec![action])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub async fn external_events(r: &Arc<Ref>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult {
|
pub fn external_events(r: &Arc<Ref>, debtor: &Arc<Debtor>, events: PendingEventQueue) -> ActorResult {
|
||||||
r.addr.mailbox.send(debtor, events)
|
send_actions(&r.addr.mailbox.tx, debtor, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ref {
|
impl Ref {
|
||||||
|
pub fn with_entity<R, F: FnOnce(&mut dyn Entity) -> R>(&self, f: F) -> R {
|
||||||
|
f(&mut **self.addr.target.write().expect("unpoisoned"))
|
||||||
|
}
|
||||||
|
|
||||||
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 = Ref {
|
||||||
addr: Arc::clone(&self.addr),
|
addr: Arc::clone(&self.addr),
|
||||||
|
@ -692,14 +700,14 @@ impl Ref {
|
||||||
Ok(Arc::new(r))
|
Ok(Arc::new(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rewrite(&self, mut a: _Any) -> Option<Assertion> {
|
pub fn rewrite(&self, mut a: _Any) -> Option<_Any> {
|
||||||
for c in &self.attenuation {
|
for c in &self.attenuation {
|
||||||
match c.rewrite(&a) {
|
match c.rewrite(&a) {
|
||||||
Some(v) => a = v,
|
Some(v) => a = v,
|
||||||
None => return None,
|
None => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Assertion(a))
|
Some(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -455,7 +455,10 @@ pub async fn input_loop(
|
||||||
#[must_use]
|
#[must_use]
|
||||||
async fn s<M: Into<_Any>>(relay: &Arc<Ref>, debtor: &Arc<Debtor>, m: M) -> ActorResult {
|
async fn s<M: Into<_Any>>(relay: &Arc<Ref>, debtor: &Arc<Debtor>, m: M) -> ActorResult {
|
||||||
debtor.ensure_clear_funds().await;
|
debtor.ensure_clear_funds().await;
|
||||||
external_event(relay, debtor, Event::Message(Box::new(Message { body: Assertion(m.into()) }))).await
|
let m = m.into();
|
||||||
|
let relay = Arc::clone(relay);
|
||||||
|
external_event(&Arc::clone(&relay), debtor, Box::new(
|
||||||
|
move |t| relay.with_entity(|e| e.message(t, m))))
|
||||||
}
|
}
|
||||||
|
|
||||||
let debtor = Debtor::new(crate::name!("input-loop"));
|
let debtor = Debtor::new(crate::name!("input-loop"));
|
||||||
|
|
Loading…
Reference in New Issue