From 815feaa4a7917249086a677d7130e66204937e44 Mon Sep 17 00:00:00 2001 From: Avril Date: Sun, 17 Jan 2021 06:19:10 +0000 Subject: [PATCH] state service + supevisor prep --- src/ext.rs | 38 +++++++++++++++++++++++++++++++- src/main.rs | 2 ++ src/state/service.rs | 52 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/ext.rs b/src/ext.rs index 8c99137..89e770b 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -540,6 +540,7 @@ pub trait AnyCloneable: mopa::Any { fn clone_dyn(&self) -> Box; fn clone_dyn_any(&self) -> Box; + fn clone_dyn_any_sync(&self) -> Box; } mopafy!(AnyCloneable); @@ -551,6 +552,9 @@ impl AnyCloneable for T #[inline] fn clone_dyn_any(&self) -> Box { Box::new(self.clone()) } + fn clone_dyn_any_sync(&self) -> Box { + Box::new(self.clone()) + } } /// A dynamically clonable heap allocated polymorphic `Any` object. @@ -580,6 +584,8 @@ impl Clone for DynCloneable mod maybe_iter { + use std::iter::{once, Once, Chain}; + #[derive(Debug, Clone)] enum Inner { @@ -598,7 +604,7 @@ mod maybe_iter /// Create a single element iterator pub fn one>(from: U) -> Self { - Self(Inner::One(std::iter::once(from.into()))) + Self(Inner::One(once(from.into()))) } /// Create a new instance from an iterator pub fn many>(from: U) -> Self @@ -610,8 +616,27 @@ mod maybe_iter { Self(Inner::None) } + + /// Create a new instance from an iterator. + /// + /// # Not using `FromIterator`. + /// 0, 1, many.. will be respected, with no unneeded heap allocations. This is not currently possible with the `FromIterator` trait. + pub fn from_iter>(from: I2) -> MaybeIter, Once>, I2::IntoIter>, T> + { + let mut iter = from.into_iter(); + MaybeIter(match (iter.next(), iter.next()) { + (Some(first), None) => Inner::One(once(first)), + (Some(first), Some(second)) => { + Inner::Some(once(first) + .chain(once(second)) + .chain(iter)) + }, + _ => Inner::None, + }) + } } + impl From> for MaybeIter where I: Iterator, U: IntoIterator @@ -649,6 +674,17 @@ mod maybe_iter } } + impl> std::iter::DoubleEndedIterator for MaybeIter + where I: std::iter::DoubleEndedIterator + { + fn next_back(&mut self) -> Option { + match &mut self.0 { + Inner::Some(x) => x.next_back(), + Inner::One(x) => x.next_back(), + Inner::None => None, + } + } + } impl> std::iter::FusedIterator for MaybeIter where I: std::iter::FusedIterator{} impl> ExactSizeIterator for MaybeIter diff --git a/src/main.rs b/src/main.rs index 820af5c..92bcabb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,9 @@ #[macro_use] extern crate mopa; #[macro_use] extern crate cfg_if; +#[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; +#[allow(unused_imports)] use color_eyre::{ eyre::{ WrapErr as _, diff --git a/src/state/service.rs b/src/state/service.rs index 3911ef4..90fb0dc 100644 --- a/src/state/service.rs +++ b/src/state/service.rs @@ -19,6 +19,7 @@ use std::collections::{BTreeMap}; id_type!(ServiceSubID; "Optional ID for filtering directed broadcast messages"); +id_type!(BroadcastID; "Each broadcast message has a unique ID."); /// Signal the shutdown method to the supervisor. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] @@ -82,11 +83,13 @@ pub(super) struct Supervisor /// /// These objects can be cloned and downcasted, becaause they are atomically refcounted if that is more desireable. #[derive(Clone)] +#[repr(transparent)] pub struct ServiceEventObject(Arc); shim_debug!(ServiceEventObject); /// A weak reference to a `ServiceEventObject`. #[derive(Clone)] +#[repr(transparent)] pub struct ServiceEventObjectRef(Weak); shim_debug!(ServiceEventObjectRef); @@ -110,11 +113,21 @@ impl ServiceEventObjectRef None => Err(self), } } + + /// Check if the object has not been destroyed yet. + pub fn is_alive(&self) -> bool + { + self.0.strong_count() > 0 + } } impl ServiceEventObject { + pub fn clone_inner(&self) -> Self + { + Self(Arc::from(self.0.clone_dyn_any_sync())) + } /// Get a weak reference counted handle to the object, without cloning the object itself. pub fn clone_weak(&self) -> ServiceEventObjectRef { @@ -125,7 +138,7 @@ impl ServiceEventObject /// /// This will fail if: /// * The downcasted type is invalid - #[inline] pub fn downcast_clone(&self) -> Option + #[inline] pub fn downcast_clone(&self) -> Option { self.downcast_ref::().map(|x| *x.clone_dyn_any().downcast().unwrap()) } @@ -134,7 +147,7 @@ impl ServiceEventObject /// This will fail if: /// * The downcasted type is invalid /// * There are other references to this object (created through `clone_ref()`.). - pub fn try_into_downcast(self) -> Result + pub fn try_into_downcast(self) -> Result { match Arc::downcast(self.0) { @@ -153,12 +166,12 @@ impl ServiceEventObject } /// Try to downcast the object into a concrete type - #[inline] pub fn is(&self) -> bool + #[inline] pub fn is(&self) -> bool { self.0.as_ref().is::() } /// Try to downcast the object into a concrete type - #[inline] pub fn downcast_ref(&self) -> Option<&T> + #[inline] pub fn downcast_ref(&self) -> Option<&T> { self.0.as_ref().downcast_ref::() } @@ -168,7 +181,11 @@ impl ServiceEventObject #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] pub enum ServiceEventKind { - + /// Does nothing. + /// + /// # Associated object + /// `()`. + Ping, /// Does nothing. /// /// # Associated object @@ -190,6 +207,8 @@ cfg_if!{ #[derive(Debug, Clone)] pub struct ServiceEvent { + bc_id: BroadcastID, + kind: ServiceEventKind, directed: Option>, obj: Option, @@ -197,8 +216,29 @@ pub struct ServiceEvent impl ServiceEvent { + /// Create a new event to be broadcast + fn new(kind: ServiceEventKind, directed: Option>, obj: Option) -> Self + where T: Any + Send + Sync + 'static + { + Self { + bc_id: BroadcastID::id_new(), + kind, + directed: directed.map(|x| x.into_iter().collect()).and_then(|n: SESet<_>| if n.len() < 1 { + None + } else { + Some(n) + }), + obj: obj.map(|x| ServiceEventObject(Arc::new(x))), + } + } + + #[inline] pub fn id(&self) -> &BroadcastID + { + &self.bc_id + } + /// The kind of this event. - pub fn kind(&self) -> ServiceEventKind + #[inline] pub fn kind(&self) -> ServiceEventKind { self.kind }