|
|
@ -15,7 +15,7 @@ use crate::service::{
|
|
|
|
use std::{error, fmt};
|
|
|
|
use std::{error, fmt};
|
|
|
|
use std::sync::Weak;
|
|
|
|
use std::sync::Weak;
|
|
|
|
use std::any::Any;
|
|
|
|
use std::any::Any;
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use std::collections::{BTreeMap};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id_type!(ServiceSubID; "Optional ID for filtering directed broadcast messages");
|
|
|
|
id_type!(ServiceSubID; "Optional ID for filtering directed broadcast messages");
|
|
|
@ -80,36 +80,16 @@ pub(super) struct Supervisor
|
|
|
|
|
|
|
|
|
|
|
|
/// Object sent through the broadcast channel.
|
|
|
|
/// Object sent through the broadcast channel.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// These objects can be cloned and downcasted, but can also be atomically refcounted if that is more desireable.
|
|
|
|
/// These objects can be cloned and downcasted, becaause they are atomically refcounted if that is more desireable.
|
|
|
|
///
|
|
|
|
#[derive(Clone)]
|
|
|
|
/// # Cloning
|
|
|
|
pub struct ServiceEventObject(Arc<dyn Any + Send + Sync + 'static>);
|
|
|
|
/// The implementation of `Clone` for this instance clones the inner object, not the refcount. Use `clone_ref()` to *just* clone the refcount.
|
|
|
|
|
|
|
|
/// To downcast and clone the inner object without an extra `Arc` allocation, use `downcast_clone()` or `downcast().map(Clone::clone)`.
|
|
|
|
|
|
|
|
pub struct ServiceEventObject(Arc<dyn AnyCloneable + Send + Sync + 'static>);
|
|
|
|
|
|
|
|
shim_debug!(ServiceEventObject);
|
|
|
|
shim_debug!(ServiceEventObject);
|
|
|
|
|
|
|
|
|
|
|
|
/// A weak reference to a `ServiceEventObject`.
|
|
|
|
/// A weak reference to a `ServiceEventObject`.
|
|
|
|
#[derive(Clone)]
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ServiceEventObjectRef(Weak<dyn AnyCloneable + Send + Sync + 'static>);
|
|
|
|
pub struct ServiceEventObjectRef(Weak<dyn Any + Send + Sync + 'static>);
|
|
|
|
shim_debug!(ServiceEventObjectRef);
|
|
|
|
shim_debug!(ServiceEventObjectRef);
|
|
|
|
|
|
|
|
|
|
|
|
/// Wrapper used when broadcasting to prevent useless inner object clones.
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
|
|
struct EventObjectRefCloneWrap(ServiceEventObject);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Clone for EventObjectRefCloneWrap
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
|
|
|
Self(self.0.clone_ref())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Clone for ServiceEventObject
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
|
|
|
Self(Arc::from(self.0.as_ref().clone_dyn()))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl ServiceEventObjectRef
|
|
|
|
impl ServiceEventObjectRef
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/// Try to upgrade to a concrete reference, and then clone the inner object.
|
|
|
|
/// Try to upgrade to a concrete reference, and then clone the inner object.
|
|
|
@ -135,12 +115,6 @@ impl ServiceEventObjectRef
|
|
|
|
|
|
|
|
|
|
|
|
impl ServiceEventObject
|
|
|
|
impl ServiceEventObject
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/// Get an owned reference counted handle to the object, without cloning the object itself.
|
|
|
|
|
|
|
|
pub fn clone_ref(&self) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Self(Arc::clone(&self.0))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Get a weak reference counted handle to the object, without cloning the object itself.
|
|
|
|
/// Get a weak reference counted handle to the object, without cloning the object itself.
|
|
|
|
pub fn clone_weak(&self) -> ServiceEventObjectRef
|
|
|
|
pub fn clone_weak(&self) -> ServiceEventObjectRef
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -164,8 +138,11 @@ impl ServiceEventObject
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match Arc::downcast(self.0)
|
|
|
|
match Arc::downcast(self.0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Ok(v) => v,
|
|
|
|
Ok(v) => match Arc::try_unwrap(v) {
|
|
|
|
Err(e) => Self(e),
|
|
|
|
Ok(v) => Ok(v),
|
|
|
|
|
|
|
|
Err(s) => Err(Self(s)),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Err(e) => Err(Self(e)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -176,14 +153,14 @@ impl ServiceEventObject
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Try to downcast the object into a concrete type
|
|
|
|
/// Try to downcast the object into a concrete type
|
|
|
|
#[inline] pub fn is<T: AnyCloneable + Send + Sync + 'static>(&self) -> Option<&T>
|
|
|
|
#[inline] pub fn is<T: AnyCloneable + Send + Sync + 'static>(&self) -> bool
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self.0.is()
|
|
|
|
self.0.as_ref().is::<T>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Try to downcast the object into a concrete type
|
|
|
|
/// Try to downcast the object into a concrete type
|
|
|
|
#[inline] pub fn downcast_ref<T: AnyCloneable + Send + Sync + 'static>(&self) -> Option<&T>
|
|
|
|
#[inline] pub fn downcast_ref<T: AnyCloneable + Send + Sync + 'static>(&self) -> Option<&T>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self.0.downcast_ref()
|
|
|
|
self.0.as_ref().downcast_ref::<T>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -199,13 +176,23 @@ pub enum ServiceEventKind
|
|
|
|
KeepAlive,
|
|
|
|
KeepAlive,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cfg_if!{
|
|
|
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
|
|
|
/// Type used for directed array.
|
|
|
|
|
|
|
|
/// Currently testing `smolset` over eagerly allocating.
|
|
|
|
|
|
|
|
type SESet<T> = smolset::SmolSet<[T; 1]>;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
type SESet<T> = std::collections::HashSet<T>;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// An event outputted from a state service's broadcast stream
|
|
|
|
/// An event outputted from a state service's broadcast stream
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct ServiceEvent
|
|
|
|
pub struct ServiceEvent
|
|
|
|
{
|
|
|
|
{
|
|
|
|
kind: ServiceEventKind,
|
|
|
|
kind: ServiceEventKind,
|
|
|
|
directed: Option<MaybeVec<ServiceSubID>>,
|
|
|
|
directed: Option<SESet<ServiceSubID>>,
|
|
|
|
obj: Option<EventObjectRefCloneWrap>,
|
|
|
|
obj: Option<ServiceEventObject>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ServiceEvent
|
|
|
|
impl ServiceEvent
|
|
|
@ -220,7 +207,7 @@ impl ServiceEvent
|
|
|
|
pub fn is_directed_for(&self, whom: &ServiceSubID) -> bool
|
|
|
|
pub fn is_directed_for(&self, whom: &ServiceSubID) -> bool
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if let Some(yes) = self.directed.as_ref() {
|
|
|
|
if let Some(yes) = self.directed.as_ref() {
|
|
|
|
yes == whom
|
|
|
|
yes.contains(whom)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -234,25 +221,25 @@ impl ServiceEvent
|
|
|
|
/// Check who this event is directed to.
|
|
|
|
/// Check who this event is directed to.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// If it is not directed, an empty slice will be returned.
|
|
|
|
/// If it is not directed, an empty slice will be returned.
|
|
|
|
pub fn directed_to(&self) -> &[&ServiceSubID]
|
|
|
|
pub fn directed_to(&self) -> impl Iterator<Item = &'_ ServiceSubID> + '_
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match self.directed.as_ref()
|
|
|
|
match self.directed.as_ref()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Some(yes) => &yes[..],
|
|
|
|
Some(yes) => MaybeIter::many(yes.iter()),
|
|
|
|
None => &[],
|
|
|
|
None => MaybeIter::none(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Get a reference to the object, if there is one.
|
|
|
|
/// Get a reference to the object, if there is one.
|
|
|
|
pub fn obj_ref(&self) -> Option<&ServiceEventObject>
|
|
|
|
pub fn obj_ref(&self) -> Option<&ServiceEventObject>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self.obj.as_ref().map(|x| x.0)
|
|
|
|
self.obj.as_ref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Get a mutable reference to the object, if there is one.
|
|
|
|
/// Get a mutable reference to the object, if there is one.
|
|
|
|
pub fn obj_mut(&mut self) -> Option<&mut ServiceEventObject>
|
|
|
|
pub fn obj_mut(&mut self) -> Option<&mut ServiceEventObject>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
self.obj.as_mut().map(|x| x.0)
|
|
|
|
self.obj.as_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Try to consume into the inner object. If there is no object, return self.
|
|
|
|
/// Try to consume into the inner object. If there is no object, return self.
|
|
|
@ -266,6 +253,7 @@ impl ServiceEvent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<ServiceEvent> for Option<ServiceEventObject>
|
|
|
|
impl From<ServiceEvent> for Option<ServiceEventObject>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#[inline] fn from(from: ServiceEvent) -> Self
|
|
|
|
#[inline] fn from(from: ServiceEvent) -> Self
|
|
|
@ -282,7 +270,7 @@ impl TryFrom<ServiceEvent> for ServiceEventObject
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match from.obj
|
|
|
|
match from.obj
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Some(obj) => Ok(obj.0),
|
|
|
|
Some(obj) => Ok(obj),
|
|
|
|
None => Err(NoObjectError),
|
|
|
|
None => Err(NoObjectError),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|