forked from ROMEO/nexosim
Remove the LineId API
This was probably never used.
This commit is contained in:
parent
0f1d876aed
commit
3c1056d699
@ -91,11 +91,3 @@ pub use sink::{
|
||||
event_buffer::EventBuffer, event_slot::EventSlot, EventSink, EventSinkStream, EventSinkWriter,
|
||||
};
|
||||
pub use source::{EventSource, QuerySource, ReplyReceiver};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
/// Unique identifier for a connection between two ports.
|
||||
pub struct LineId(u64);
|
||||
|
||||
/// Error raised when the specified line cannot be found.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct LineError {}
|
||||
|
@ -4,7 +4,7 @@ mod sender;
|
||||
use std::fmt;
|
||||
|
||||
use crate::model::Model;
|
||||
use crate::ports::{EventSink, LineError, LineId};
|
||||
use crate::ports::EventSink;
|
||||
use crate::ports::{InputFn, ReplierFn};
|
||||
use crate::simulation::Address;
|
||||
use crate::util::cached_rw_lock::CachedRwLock;
|
||||
@ -43,20 +43,20 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
/// The input port must be an asynchronous method of a model of type `M`
|
||||
/// taking as argument a value of type `T` plus, optionally, a scheduler
|
||||
/// reference.
|
||||
pub fn connect<M, F, S>(&mut self, input: F, address: impl Into<Address<M>>) -> LineId
|
||||
pub fn connect<M, F, S>(&mut self, input: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
F: for<'a> InputFn<'a, M, T, S> + Clone,
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(InputSender::new(input, address.into().0));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds a connection to an event sink such as an
|
||||
/// [`EventSlot`](crate::ports::EventSlot) or
|
||||
/// [`EventBuffer`](crate::ports::EventBuffer).
|
||||
pub fn connect_sink<S: EventSink<T>>(&mut self, sink: &S) -> LineId {
|
||||
pub fn connect_sink<S: EventSink<T>>(&mut self, sink: &S) {
|
||||
let sender = Box::new(EventSinkSender::new(sink.writer()));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
}
|
||||
@ -70,12 +70,7 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
/// The input port must be an asynchronous method of a model of type `M`
|
||||
/// taking as argument a value of the type returned by the mapping
|
||||
/// closure plus, optionally, a context reference.
|
||||
pub fn map_connect<M, C, F, U, S>(
|
||||
&mut self,
|
||||
map: C,
|
||||
input: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
pub fn map_connect<M, C, F, U, S>(&mut self, map: C, input: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
C: Fn(&T) -> U + Send + Sync + 'static,
|
||||
@ -84,7 +79,7 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(MapInputSender::new(map, input, address.into().0));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting connection to an event sink such as an
|
||||
@ -93,14 +88,14 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
///
|
||||
/// Events are mapped to another type using the closure provided in
|
||||
/// argument.
|
||||
pub fn map_connect_sink<C, U, S>(&mut self, map: C, sink: &S) -> LineId
|
||||
pub fn map_connect_sink<C, U, S>(&mut self, map: C, sink: &S)
|
||||
where
|
||||
C: Fn(&T) -> U + Send + Sync + 'static,
|
||||
U: Send + 'static,
|
||||
S: EventSink<U>,
|
||||
{
|
||||
let sender = Box::new(MapEventSinkSender::new(map, sink.writer()));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting, filtered connection to an input port of the
|
||||
@ -117,8 +112,7 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
filter_map: C,
|
||||
input: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: Fn(&T) -> Option<U> + Send + Sync + 'static,
|
||||
F: for<'a> InputFn<'a, M, U, S> + Clone,
|
||||
@ -130,7 +124,7 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
input,
|
||||
address.into().0,
|
||||
));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting connection to an event sink such as an
|
||||
@ -139,33 +133,14 @@ impl<T: Clone + Send + 'static> Output<T> {
|
||||
///
|
||||
/// Events are mapped to another type using the closure provided in
|
||||
/// argument.
|
||||
pub fn filter_map_connect_sink<C, U, S>(&mut self, filter_map: C, sink: &S) -> LineId
|
||||
pub fn filter_map_connect_sink<C, U, S>(&mut self, filter_map: C, sink: &S)
|
||||
where
|
||||
C: Fn(&T) -> Option<U> + Send + Sync + 'static,
|
||||
U: Send + 'static,
|
||||
S: EventSink<U>,
|
||||
{
|
||||
let sender = Box::new(FilterMapEventSinkSender::new(filter_map, sink.writer()));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
}
|
||||
|
||||
/// Removes the connection specified by the `LineId` parameter.
|
||||
///
|
||||
/// It is a logic error to specify a line identifier from another
|
||||
/// [`Output`], [`Requestor`], [`EventSource`](crate::ports::EventSource) or
|
||||
/// [`QuerySource`](crate::ports::QuerySource) instance and may result in
|
||||
/// the disconnection of an arbitrary endpoint.
|
||||
pub fn disconnect(&mut self, line_id: LineId) -> Result<(), LineError> {
|
||||
if self.broadcaster.write().unwrap().remove(line_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LineError {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all connections.
|
||||
pub fn disconnect_all(&mut self) {
|
||||
self.broadcaster.write().unwrap().clear();
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Broadcasts an event to all connected input ports.
|
||||
@ -219,14 +194,14 @@ impl<T: Clone + Send + 'static, R: Send + 'static> Requestor<T, R> {
|
||||
/// The replier port must be an asynchronous method of a model of type `M`
|
||||
/// returning a value of type `R` and taking as argument a value of type `T`
|
||||
/// plus, optionally, a context reference.
|
||||
pub fn connect<M, F, S>(&mut self, replier: F, address: impl Into<Address<M>>) -> LineId
|
||||
pub fn connect<M, F, S>(&mut self, replier: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
F: for<'a> ReplierFn<'a, M, T, R, S> + Clone,
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(ReplierSender::new(replier, address.into().0));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting connection to a replier port of the model
|
||||
@ -245,8 +220,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> Requestor<T, R> {
|
||||
reply_map: D,
|
||||
replier: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: Fn(&T) -> U + Send + Sync + 'static,
|
||||
D: Fn(Q) -> R + Send + Sync + 'static,
|
||||
@ -261,7 +235,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> Requestor<T, R> {
|
||||
replier,
|
||||
address.into().0,
|
||||
));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting, filtered connection to a replier port of the
|
||||
@ -280,8 +254,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> Requestor<T, R> {
|
||||
reply_map: D,
|
||||
replier: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: Fn(&T) -> Option<U> + Send + Sync + 'static,
|
||||
D: Fn(Q) -> R + Send + Sync + 'static,
|
||||
@ -296,26 +269,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> Requestor<T, R> {
|
||||
replier,
|
||||
address.into().0,
|
||||
));
|
||||
self.broadcaster.write().unwrap().add(sender)
|
||||
}
|
||||
|
||||
/// Removes the connection specified by the `LineId` parameter.
|
||||
///
|
||||
/// It is a logic error to specify a line identifier from another
|
||||
/// [`Requestor`], [`Output`], [`EventSource`](crate::ports::EventSource) or
|
||||
/// [`QuerySource`](crate::ports::QuerySource) instance and may result in
|
||||
/// the disconnection of an arbitrary endpoint.
|
||||
pub fn disconnect(&mut self, line_id: LineId) -> Result<(), LineError> {
|
||||
if self.broadcaster.write().unwrap().remove(line_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LineError {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all connections.
|
||||
pub fn disconnect_all(&mut self) {
|
||||
self.broadcaster.write().unwrap().clear();
|
||||
self.broadcaster.write().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Broadcasts a query to all connected replier ports.
|
||||
|
@ -6,7 +6,6 @@ use std::task::{Context, Poll};
|
||||
use diatomic_waker::WakeSink;
|
||||
|
||||
use super::sender::{RecycledFuture, SendError, Sender};
|
||||
use super::LineId;
|
||||
use crate::util::task_set::TaskSet;
|
||||
|
||||
/// An object that can efficiently broadcast messages to several addresses.
|
||||
@ -24,10 +23,8 @@ use crate::util::task_set::TaskSet;
|
||||
/// - the outputs of all sender futures are returned all at once rather than
|
||||
/// with an asynchronous iterator (a.k.a. async stream).
|
||||
pub(super) struct BroadcasterInner<T: Clone, R> {
|
||||
/// Line identifier for the next port to be connected.
|
||||
next_line_id: u64,
|
||||
/// The list of senders with their associated line identifier.
|
||||
senders: Vec<(LineId, Box<dyn Sender<T, R>>)>,
|
||||
senders: Vec<Box<dyn Sender<T, R>>>,
|
||||
/// Fields explicitly borrowed by the `BroadcastFuture`.
|
||||
shared: Shared<R>,
|
||||
}
|
||||
@ -38,42 +35,17 @@ impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) -> LineId {
|
||||
assert!(self.next_line_id != u64::MAX);
|
||||
let line_id = LineId(self.next_line_id);
|
||||
self.next_line_id += 1;
|
||||
|
||||
self.senders.push((line_id, sender));
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) {
|
||||
assert!(self.senders.len() < (u32::MAX as usize - 2));
|
||||
self.senders.push(sender);
|
||||
self.shared.outputs.push(None);
|
||||
|
||||
// The storage is alway an empty vector so we just book some capacity.
|
||||
if let Some(storage) = self.shared.storage.as_mut() {
|
||||
let _ = storage.try_reserve(self.senders.len());
|
||||
};
|
||||
|
||||
line_id
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
if let Some(pos) = self.senders.iter().position(|s| s.0 == id) {
|
||||
self.senders.swap_remove(pos);
|
||||
self.shared.outputs.truncate(self.senders.len());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.senders.clear();
|
||||
self.shared.outputs.clear();
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
@ -98,13 +70,13 @@ impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
while let Some(sender) = iter.next() {
|
||||
// Move the argument rather than clone it for the last future.
|
||||
if iter.len() == 0 {
|
||||
if let Some(fut) = sender.1.send_owned(arg) {
|
||||
if let Some(fut) = sender.send_owned(arg) {
|
||||
futures.push(fut);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some(fut) = sender.1.send(&arg) {
|
||||
if let Some(fut) = sender.send(&arg) {
|
||||
futures.push(fut);
|
||||
}
|
||||
}
|
||||
@ -120,7 +92,6 @@ impl<T: Clone, R> Default for BroadcasterInner<T, R> {
|
||||
let wake_src = wake_sink.source();
|
||||
|
||||
Self {
|
||||
next_line_id: 0,
|
||||
senders: Vec::new(),
|
||||
shared: Shared {
|
||||
wake_sink,
|
||||
@ -135,7 +106,6 @@ impl<T: Clone, R> Default for BroadcasterInner<T, R> {
|
||||
impl<T: Clone, R> Clone for BroadcasterInner<T, R> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
next_line_id: self.next_line_id,
|
||||
senders: self.senders.clone(),
|
||||
shared: self.shared.clone(),
|
||||
}
|
||||
@ -160,24 +130,12 @@ impl<T: Clone> EventBroadcaster<T> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, ()>>) -> LineId {
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, ()>>) {
|
||||
self.inner.add(sender)
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
self.inner.remove(id)
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.inner.clear();
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
pub(super) fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
@ -190,7 +148,7 @@ impl<T: Clone> EventBroadcaster<T> {
|
||||
[] => Ok(()),
|
||||
|
||||
// One sender at most.
|
||||
[sender] => match sender.1.send_owned(arg) {
|
||||
[sender] => match sender.send_owned(arg) {
|
||||
None => Ok(()),
|
||||
Some(fut) => fut.await.map_err(|_| BroadcastError {}),
|
||||
},
|
||||
@ -233,24 +191,12 @@ impl<T: Clone, R> QueryBroadcaster<T, R> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) -> LineId {
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) {
|
||||
self.inner.add(sender)
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
self.inner.remove(id)
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.inner.clear();
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
pub(super) fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
@ -267,7 +213,7 @@ impl<T: Clone, R> QueryBroadcaster<T, R> {
|
||||
|
||||
// One sender at most.
|
||||
[sender] => {
|
||||
if let Some(fut) = sender.1.send_owned(arg) {
|
||||
if let Some(fut) = sender.send_owned(arg) {
|
||||
let output = fut.await.map_err(|_| BroadcastError {})?;
|
||||
self.inner.shared.outputs[0] = Some(output);
|
||||
|
||||
|
@ -7,7 +7,6 @@ use std::time::Duration;
|
||||
|
||||
use crate::model::Model;
|
||||
use crate::ports::InputFn;
|
||||
use crate::ports::{LineError, LineId};
|
||||
use crate::simulation::{
|
||||
Action, ActionKey, Address, KeyedOnceAction, KeyedPeriodicAction, OnceAction, PeriodicAction,
|
||||
};
|
||||
@ -43,14 +42,14 @@ impl<T: Clone + Send + 'static> EventSource<T> {
|
||||
/// The input port must be an asynchronous method of a model of type `M`
|
||||
/// taking as argument a value of type `T` plus, optionally, a scheduler
|
||||
/// reference.
|
||||
pub fn connect<M, F, S>(&mut self, input: F, address: impl Into<Address<M>>) -> LineId
|
||||
pub fn connect<M, F, S>(&mut self, input: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
F: for<'a> InputFn<'a, M, T, S> + Clone,
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(InputSender::new(input, address.into().0));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting connection to an input port of the model
|
||||
@ -62,12 +61,7 @@ impl<T: Clone + Send + 'static> EventSource<T> {
|
||||
/// The input port must be an asynchronous method of a model of type `M`
|
||||
/// taking as argument a value of the type returned by the mapping closure
|
||||
/// plus, optionally, a context reference.
|
||||
pub fn map_connect<M, C, F, U, S>(
|
||||
&mut self,
|
||||
map: C,
|
||||
input: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
pub fn map_connect<M, C, F, U, S>(&mut self, map: C, input: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
C: for<'a> Fn(&'a T) -> U + Send + 'static,
|
||||
@ -76,7 +70,7 @@ impl<T: Clone + Send + 'static> EventSource<T> {
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(MapInputSender::new(map, input, address.into().0));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting, filtered connection to an input port of the
|
||||
@ -93,8 +87,7 @@ impl<T: Clone + Send + 'static> EventSource<T> {
|
||||
map: C,
|
||||
input: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: for<'a> Fn(&'a T) -> Option<U> + Send + 'static,
|
||||
F: for<'a> InputFn<'a, M, U, S> + Clone,
|
||||
@ -102,26 +95,7 @@ impl<T: Clone + Send + 'static> EventSource<T> {
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(FilterMapInputSender::new(map, input, address.into().0));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
}
|
||||
|
||||
/// Removes the connection specified by the `LineId` parameter.
|
||||
///
|
||||
/// It is a logic error to specify a line identifier from another
|
||||
/// [`EventSource`], [`QuerySource`], [`Output`](crate::ports::Output) or
|
||||
/// [`Requestor`](crate::ports::Requestor) instance and may result in the
|
||||
/// disconnection of an arbitrary endpoint.
|
||||
pub fn disconnect(&mut self, line_id: LineId) -> Result<(), LineError> {
|
||||
if self.broadcaster.lock().unwrap().remove(line_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LineError {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all connections.
|
||||
pub fn disconnect_all(&mut self) {
|
||||
self.broadcaster.lock().unwrap().clear();
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Returns an action which, when processed, broadcasts an event to all
|
||||
@ -248,14 +222,14 @@ impl<T: Clone + Send + 'static, R: Send + 'static> QuerySource<T, R> {
|
||||
/// The replier port must be an asynchronous method of a model of type `M`
|
||||
/// returning a value of type `R` and taking as argument a value of type `T`
|
||||
/// plus, optionally, a context reference.
|
||||
pub fn connect<M, F, S>(&mut self, replier: F, address: impl Into<Address<M>>) -> LineId
|
||||
pub fn connect<M, F, S>(&mut self, replier: F, address: impl Into<Address<M>>)
|
||||
where
|
||||
M: Model,
|
||||
F: for<'a> ReplierFn<'a, M, T, R, S> + Clone,
|
||||
S: Send + 'static,
|
||||
{
|
||||
let sender = Box::new(ReplierSender::new(replier, address.into().0));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting connection to a replier port of the model
|
||||
@ -274,8 +248,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> QuerySource<T, R> {
|
||||
reply_map: D,
|
||||
replier: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: for<'a> Fn(&'a T) -> U + Send + 'static,
|
||||
D: Fn(Q) -> R + Send + Sync + 'static,
|
||||
@ -290,7 +263,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> QuerySource<T, R> {
|
||||
replier,
|
||||
address.into().0,
|
||||
));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Adds an auto-converting, filtered connection to a replier port of the
|
||||
@ -309,8 +282,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> QuerySource<T, R> {
|
||||
reply_map: D,
|
||||
replier: F,
|
||||
address: impl Into<Address<M>>,
|
||||
) -> LineId
|
||||
where
|
||||
) where
|
||||
M: Model,
|
||||
C: for<'a> Fn(&'a T) -> Option<U> + Send + 'static,
|
||||
D: Fn(Q) -> R + Send + Sync + 'static,
|
||||
@ -325,26 +297,7 @@ impl<T: Clone + Send + 'static, R: Send + 'static> QuerySource<T, R> {
|
||||
replier,
|
||||
address.into().0,
|
||||
));
|
||||
self.broadcaster.lock().unwrap().add(sender)
|
||||
}
|
||||
|
||||
/// Removes the connection specified by the `LineId` parameter.
|
||||
///
|
||||
/// It is a logic error to specify a line identifier from another
|
||||
/// [`QuerySource`], [`EventSource`], [`Output`](crate::ports::Output) or
|
||||
/// [`Requestor`](crate::ports::Requestor) instance and may result in the
|
||||
/// disconnection of an arbitrary endpoint.
|
||||
pub fn disconnect(&mut self, line_id: LineId) -> Result<(), LineError> {
|
||||
if self.broadcaster.lock().unwrap().remove(line_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LineError {})
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all connections.
|
||||
pub fn disconnect_all(&mut self) {
|
||||
self.broadcaster.lock().unwrap().clear();
|
||||
self.broadcaster.lock().unwrap().add(sender);
|
||||
}
|
||||
|
||||
/// Returns an action which, when processed, broadcasts a query to all
|
||||
|
@ -10,7 +10,6 @@ use diatomic_waker::WakeSink;
|
||||
|
||||
use super::sender::{Sender, SenderFuture};
|
||||
|
||||
use crate::ports::LineId;
|
||||
use crate::util::task_set::TaskSet;
|
||||
|
||||
/// An object that can efficiently broadcast messages to several addresses.
|
||||
@ -24,10 +23,8 @@ use crate::util::task_set::TaskSet;
|
||||
/// does, but the outputs of all sender futures are returned all at once rather
|
||||
/// than with an asynchronous iterator (a.k.a. async stream).
|
||||
pub(super) struct BroadcasterInner<T: Clone, R> {
|
||||
/// Line identifier for the next port to be connected.
|
||||
next_line_id: u64,
|
||||
/// The list of senders with their associated line identifier.
|
||||
senders: Vec<(LineId, Box<dyn Sender<T, R>>)>,
|
||||
senders: Vec<Box<dyn Sender<T, R>>>,
|
||||
}
|
||||
|
||||
impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
@ -36,34 +33,11 @@ impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) -> LineId {
|
||||
assert!(self.next_line_id != u64::MAX);
|
||||
let line_id = LineId(self.next_line_id);
|
||||
self.next_line_id += 1;
|
||||
|
||||
self.senders.push((line_id, sender));
|
||||
|
||||
line_id
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
if let Some(pos) = self.senders.iter().position(|s| s.0 == id) {
|
||||
self.senders.swap_remove(pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.senders.clear();
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) {
|
||||
assert!(self.senders.len() < (u32::MAX as usize - 2));
|
||||
self.senders.push(sender);
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
@ -81,12 +55,12 @@ impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
while let Some(sender) = iter.next() {
|
||||
// Move the argument for the last future to avoid undue cloning.
|
||||
if iter.len() == 0 {
|
||||
if let Some(fut) = sender.1.send_owned(arg) {
|
||||
if let Some(fut) = sender.send_owned(arg) {
|
||||
future_states.push(SenderFutureState::Pending(fut));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if let Some(fut) = sender.1.send(&arg) {
|
||||
if let Some(fut) = sender.send(&arg) {
|
||||
future_states.push(SenderFutureState::Pending(fut));
|
||||
}
|
||||
}
|
||||
@ -98,7 +72,6 @@ impl<T: Clone, R> BroadcasterInner<T, R> {
|
||||
impl<T: Clone, R> Default for BroadcasterInner<T, R> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
next_line_id: 0,
|
||||
senders: Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -121,22 +94,10 @@ impl<T: Clone + Send> EventBroadcaster<T> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, ()>>) -> LineId {
|
||||
self.inner.add(sender)
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
self.inner.remove(id)
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.inner.clear();
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, ()>>) {
|
||||
self.inner.add(sender);
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
@ -159,7 +120,7 @@ impl<T: Clone + Send> EventBroadcaster<T> {
|
||||
// No sender.
|
||||
[] => Fut::Empty,
|
||||
// One sender at most.
|
||||
[sender] => Fut::Single(sender.1.send_owned(arg)),
|
||||
[sender] => Fut::Single(sender.send_owned(arg)),
|
||||
// Possibly multiple senders.
|
||||
_ => Fut::Multiple(self.inner.futures(arg)),
|
||||
};
|
||||
@ -209,22 +170,10 @@ impl<T: Clone + Send, R: Send> QueryBroadcaster<T, R> {
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if the total count of senders would reach
|
||||
/// `u32::MAX - 1`.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) -> LineId {
|
||||
self.inner.add(sender)
|
||||
}
|
||||
|
||||
/// Removes the first sender with the specified identifier, if any.
|
||||
///
|
||||
/// Returns `true` if there was indeed a sender associated to the specified
|
||||
/// identifier.
|
||||
pub(super) fn remove(&mut self, id: LineId) -> bool {
|
||||
self.inner.remove(id)
|
||||
}
|
||||
|
||||
/// Removes all senders.
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.inner.clear();
|
||||
/// `u32::MAX - 1` due to limitations inherent to the task set
|
||||
/// implementation.
|
||||
pub(super) fn add(&mut self, sender: Box<dyn Sender<T, R>>) {
|
||||
self.inner.add(sender);
|
||||
}
|
||||
|
||||
/// Returns the number of connected senders.
|
||||
@ -247,7 +196,7 @@ impl<T: Clone + Send, R: Send> QueryBroadcaster<T, R> {
|
||||
// No sender.
|
||||
[] => Fut::Empty,
|
||||
// One sender at most.
|
||||
[sender] => Fut::Single(sender.1.send_owned(arg)),
|
||||
[sender] => Fut::Single(sender.send_owned(arg)),
|
||||
// Possibly multiple senders.
|
||||
_ => Fut::Multiple(self.inner.futures(arg)),
|
||||
};
|
||||
|
@ -76,47 +76,6 @@
|
||||
//! Any deadlocks will be reported as an [`ExecutionError::Deadlock`] error,
|
||||
//! which identifies all involved models and the amount of unprocessed messages
|
||||
//! (events or requests) in their mailboxes.
|
||||
//!
|
||||
//! ## Modifying connections during simulation
|
||||
//!
|
||||
//! Although uncommon, there is sometimes a need for connecting and/or
|
||||
//! disconnecting models after they have been migrated to the simulation.
|
||||
//! Likewise, one may want to connect or disconnect an
|
||||
//! [`EventSlot`](crate::ports::EventSlot) or
|
||||
//! [`EventBuffer`](crate::ports::EventBuffer) after the simulation has been
|
||||
//! instantiated.
|
||||
//!
|
||||
//! There is actually a very simple solution to this problem: since the
|
||||
//! [`InputFn`] trait also matches closures of type `FnOnce(&mut impl Model)`,
|
||||
//! it is enough to invoke [`Simulation::process_event()`] with a closure that
|
||||
//! connects or disconnects a port, such as:
|
||||
//!
|
||||
//! ```
|
||||
//! # use asynchronix::model::{Context, Model};
|
||||
//! # use asynchronix::ports::Output;
|
||||
//! # use asynchronix::time::MonotonicTime;
|
||||
//! # use asynchronix::simulation::{Mailbox, SimInit};
|
||||
//! # pub struct ModelA {
|
||||
//! # pub output: Output<i32>,
|
||||
//! # }
|
||||
//! # impl Model for ModelA {};
|
||||
//! # pub struct ModelB {}
|
||||
//! # impl ModelB {
|
||||
//! # pub fn input(&mut self, value: i32) {}
|
||||
//! # }
|
||||
//! # impl Model for ModelB {};
|
||||
//! # let modelA_addr = Mailbox::<ModelA>::new().address();
|
||||
//! # let modelB_addr = Mailbox::<ModelB>::new().address();
|
||||
//! # let mut simu = SimInit::new().init(MonotonicTime::EPOCH)?.0;
|
||||
//! simu.process_event(
|
||||
//! |m: &mut ModelA| {
|
||||
//! m.output.connect(ModelB::input, modelB_addr);
|
||||
//! },
|
||||
//! (),
|
||||
//! &modelA_addr
|
||||
//! )?;
|
||||
//! # Ok::<(), asynchronix::simulation::SimulationError>(())
|
||||
//! ```
|
||||
mod mailbox;
|
||||
mod scheduler;
|
||||
mod sim_init;
|
||||
|
Loading…
x
Reference in New Issue
Block a user