diff --git a/Cargo.lock b/Cargo.lock index 51464ca..d9f2a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,40 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" + +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + [[package]] name = "autocfg" version = "0.1.7" @@ -12,6 +47,20 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" +dependencies = [ + "addr2line", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.12.3" @@ -115,6 +164,19 @@ dependencies = [ "bitflags", ] +[[package]] +name = "color-eyre" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b29030875fd8376e4a28ef497790d5b4a7843d8d1396bf08ce46f5eec562c5c" +dependencies = [ + "backtrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", +] + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -190,6 +252,29 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -394,6 +479,12 @@ dependencies = [ "wasi 0.10.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" + [[package]] name = "h2" version = "0.2.7" @@ -503,6 +594,15 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "hyper" version = "0.13.9" @@ -538,6 +638,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indenter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4d5eb2e114fec2b7fe0fadc22888ad2658789bb7acac4dbee9cf8389f971ec8" + [[package]] name = "indexmap" version = "1.6.1" @@ -631,6 +737,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "miniz_oxide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +dependencies = [ + "adler", + "autocfg 1.0.1", +] + [[package]] name = "mio" version = "0.6.23" @@ -695,6 +811,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "mopa" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" + [[package]] name = "multipart" version = "0.17.0" @@ -734,6 +856,12 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" + [[package]] name = "once_cell" version = "1.5.2" @@ -779,6 +907,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "owo-colors" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13370dae44474229701bb69b90b4f4dca6404cb0357a2d50d635f1171dc3aa7b" + [[package]] name = "pbkdf2" version = "0.5.0" @@ -870,6 +1004,16 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1068,6 +1212,24 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "regex" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1077,6 +1239,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rustc-demangle" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" + [[package]] name = "ryu" version = "1.0.5" @@ -1242,6 +1410,24 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" +dependencies = [ + "lazy_static", +] + [[package]] name = "time" version = "0.1.44" @@ -1564,6 +1750,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1584,13 +1779,17 @@ dependencies = [ name = "yuurei" version = "0.1.0" dependencies = [ + "color-eyre", "cryptohelpers", "difference", "futures", "generational-arena", "getrandom 0.2.1", "lazy_static", + "log", + "mopa", "once_cell", + "pretty_env_logger", "serde", "sha2", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 67af577..2465dd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,13 +11,17 @@ default = ["nightly"] nightly = ["smallvec/const_generics"] [dependencies] +color-eyre = {version = "0.5.10", default-features=false} cryptohelpers = {version = "1.7.1", features=["full"]} difference = "2.0.0" futures = "0.3.8" generational-arena = "0.2.8" getrandom = "0.2.1" lazy_static = "1.4.0" +log = "0.4.11" +mopa = "0.2.2" once_cell = "1.5.2" +pretty_env_logger = "0.4.0" serde = {version = "1.0.118", features=["derive"]} sha2 = "0.9.2" smallvec = {version = "1.6.0", features= ["union", "serde", "write"]} diff --git a/src/ext.rs b/src/ext.rs index aeb363e..ba65a97 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -519,13 +519,13 @@ pub type MaybeVec = smallvec::SmallVec<[T; 1]>; } } $( - impl $($($frag)*)? ::std::ops::DerefMut for $name - { - fn deref_mut(&mut self) -> &mut ::Target + impl $($($frag)*)? ::std::ops::DerefMut for $name { - $mut_expr - } - })? + fn deref_mut(&mut self) -> &mut ::Target + { + $mut_expr + } + })? }; } @@ -533,3 +533,48 @@ pub type MaybeVec = smallvec::SmallVec<[T; 1]>; #[macro_export] macro_rules! ignore { ($expr:expr) => ({let _ = $expr;}); } + +use std::any::Any; +/// A trait for `Any` that is both `Send`, `Sync`, `'static`, and implements `Clone`. +pub trait AnyCloneable: mopa::Any +{ + fn clone_dyn(&self) -> Box; + fn clone_dyn_any(&self) -> Box; +} +mopafy!(AnyCloneable); + +impl AnyCloneable for T +{ + #[inline] fn clone_dyn(&self) -> Box { + Box::new(self.clone()) + } + #[inline] fn clone_dyn_any(&self) -> Box { + Box::new(self.clone()) + } +} + +/// A dynamically clonable heap allocated polymorphic `Any` object. +pub type DynCloneable = Box; +impl Clone for DynCloneable +{ + #[inline] fn clone(&self) -> Self { + self.clone_dyn() + } +} + +#[macro_export] macro_rules! shim_debug { + ($name:ident; $msg:literal $($tt:tt)*) => { + impl ::std::fmt::Debug for $name + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, $msg $($tt)*) + } + } + }; + ($name:ident) => { + shim_debug!($name; "", std::any::type_name::<$name>()); + } + +} + diff --git a/src/main.rs b/src/main.rs index 9c8455a..f5799df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,8 +6,19 @@ #[cfg(all(feature="nightly", test))] extern crate test; #[macro_use] extern crate serde; #[macro_use] extern crate lazy_static; +#[macro_use] extern crate log; +#[macro_use] extern crate mopa; use std::convert::{TryFrom, TryInto}; +use color_eyre::{ + eyre::{ + WrapErr as _, + self, + eyre, + }, + SectionExt, Help +}; + #[macro_use] mod ext; use ext::*; mod bytes; @@ -16,7 +27,18 @@ mod delta; mod state; mod service; +fn install() -> eyre::Result<()> +{ + color_eyre::install()?; + pretty_env_logger::init(); + + Ok(()) +} + #[tokio::main] -async fn main() { +async fn main() -> eyre::Result<()> { + install()?; println!("Hello, world!"); + + Ok(()) } diff --git a/src/service.rs b/src/service.rs index 8178975..c3f4381 100644 --- a/src/service.rs +++ b/src/service.rs @@ -14,7 +14,7 @@ use std::marker::{Send,Sync}; //pub type BoxedMessage = Box; /// A handle to a service. -pub trait Service +pub trait Service where T: Send + 'static { /// The message type to send to the service. @@ -67,3 +67,68 @@ impl fmt::Display for SubscribeError } } } + +#[macro_export] macro_rules! join_service { + ($serv:expr) => ($serv.await.map_err(|_| $crate::service::ExitStatus::Abnormal)?) +} + + +/// How a service exited +#[derive(Debug)] +#[non_exhaustive] +pub enum ExitStatus +{ + /// A graceful exit with value + Graceful(T), + /// An abnormal exit (counted as error) + /// + /// # Usage + /// Usually for panicked services, otherwise use `Self::Error`. + /// The macro `join_service!()` can be used to convert handle join errors into this + Abnormal, + /// Exit on an error report (counted as error) + Error(eyre::Report), +} + +#[derive(Debug)] +/// The error `ExitStatus::Abnormal` converts to. +pub struct AbnormalExitError; + +impl error::Error for AbnormalExitError{} +impl fmt::Display for AbnormalExitError +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "service terminated in an abnormal way") + } +} + +impl From for ExitStatus +{ + fn from(from: T) -> Self + { + Self::Error(from.into()) + } +} +impl Default for ExitStatus +{ + #[inline] + fn default() -> Self + { + Self::Graceful(T::default()) + } +} + +impl From> for eyre::Result +{ + fn from(from: ExitStatus) -> Self + { + match from { + ExitStatus::Abnormal => Err(AbnormalExitError).with_note(|| "The background worker likely panicked"), + ExitStatus::Graceful(t) => Ok(t), + ExitStatus::Error(rep) => Err(rep).wrap_err(AbnormalExitError), + } + } +} + + diff --git a/src/state/mod.rs b/src/state/mod.rs index 1d0aacc..3f8425f 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -12,6 +12,7 @@ pub mod user; pub mod post; pub mod body; +mod service; pub use service::*; mod freeze; pub use freeze::*; /// Entire post state container @@ -65,3 +66,4 @@ impl State self.0.posts.write().await } } + diff --git a/src/state/service.rs b/src/state/service.rs new file mode 100644 index 0000000..d5964f2 --- /dev/null +++ b/src/state/service.rs @@ -0,0 +1,303 @@ +//! Global state service +use super::*; +use tokio::{ + sync::{ + watch, + mpsc, + oneshot, + broadcast, + }, + task::JoinHandle, +}; +use crate::service::{ + ExitStatus, +}; +use std::{error, fmt}; +use std::sync::Weak; +use std::any::Any; +use std::collections::BTreeMap; + + +id_type!(ServiceSubID; "Optional ID for filtering directed broadcast messages"); + +/// Signal the shutdown method to the supervisor. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] +pub enum SupervisorShutdownStatus +{ + /// Signal the subtask(s) to shut down, then wait for them and exit. + Signal, + /// Drop all handles and pipes to subtask(s) then immediately exit. + Drop, + /// Keep working + Normal, + /// Restart any and all subtask(s) + Restart, +} + +impl Default for SupervisorShutdownStatus +{ + #[inline] + fn default() -> Self + { + SupervisorShutdownStatus::Normal + } +} + +/// The kind of command to send to the the service +#[derive(Debug)] +pub enum ServiceCommandKind +{ + +} + +#[derive(Debug)] +pub enum ServiceResponseKind +{ + +} + +#[derive(Debug)] +pub struct ServiceResponse(Option); + +#[derive(Debug)] +pub struct ServiceCommand +{ + kind: ServiceCommandKind, + output: oneshot::Sender, +} + +/// Supervisor responsible for spawning the state handler service. +#[derive(Debug)] +pub(super) struct Supervisor +{ + handle: JoinHandle, + + shutdown: watch::Sender, + + pipe: mpsc::Sender, + sub: BTreeMap +} + +/// Object sent through the broadcast channel. +/// +/// These objects can be cloned and downcasted, but can also be atomically refcounted if that is more desireable. +/// +/// # Cloning +/// 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); +shim_debug!(ServiceEventObject); +/// A weak reference to a `ServiceEventObject`. +#[derive(Clone)] +pub struct ServiceEventObjectRef(Weak); +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 +{ + /// Try to upgrade to a concrete reference, and then clone the inner object. + pub fn try_clone(&self) -> Option + { + match self.0.upgrade() + { + Some(arc) => Some(ServiceEventObject(arc).clone()), + None => None + } + } + /// Try to upgrade to a concrete reference. + pub fn upgrade(self) -> Result + { + match self.0.upgrade() + { + Some(arc) => Ok(ServiceEventObject(arc)), + None => Err(self), + } + } +} + + +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. + pub fn clone_weak(&self) -> ServiceEventObjectRef + { + ServiceEventObjectRef(Arc::downgrade(&self.0)) + } + + /// Try to downcast the inner object to a concrete type and then clone it. + /// + /// This will fail if: + /// * The downcasted type is invalid + #[inline] pub fn downcast_clone(&self) -> Option + { + self.downcast_ref::().map(|x| *x.clone_dyn_any().downcast().unwrap()) + } + /// Try to consume this instance into downcast. + /// + /// 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 + { + match Arc::downcast(self.0) + { + Ok(v) => v, + Err(e) => Self(e), + } + } + + /// Check if there are any other references to this object + #[inline] pub fn is_unique(&self) -> bool + { + Arc::strong_count(&self.0) == 1 + } + + /// Try to downcast the object into a concrete type + #[inline] pub fn is(&self) -> Option<&T> + { + self.0.is() + } + /// Try to downcast the object into a concrete type + #[inline] pub fn downcast_ref(&self) -> Option<&T> + { + self.0.downcast_ref() + } +} + +/// The kind of event outputted from a state service's broadcast stream +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] +pub enum ServiceEventKind +{ + + /// Does nothing. + /// + /// # Associated object + /// None. + KeepAlive, +} + +/// An event outputted from a state service's broadcast stream +#[derive(Debug, Clone)] +pub struct ServiceEvent +{ + kind: ServiceEventKind, + directed: Option>, + obj: Option, +} + +impl ServiceEvent +{ + /// The kind of this event. + pub fn kind(&self) -> ServiceEventKind + { + self.kind + } + + /// Check if this event is for you + pub fn is_directed_for(&self, whom: &ServiceSubID) -> bool + { + if let Some(yes) = self.directed.as_ref() { + yes == whom + } else { + false + } + } + /// Check if this event is directed to anyone + pub fn is_directed(&self) -> bool + { + self.directed.is_some() + } + + /// Check who this event is directed to. + /// + /// If it is not directed, an empty slice will be returned. + pub fn directed_to(&self) -> &[&ServiceSubID] + { + match self.directed.as_ref() + { + Some(yes) => &yes[..], + None => &[], + } + } + + /// Get a reference to the object, if there is one. + pub fn obj_ref(&self) -> Option<&ServiceEventObject> + { + self.obj.as_ref().map(|x| x.0) + } + + /// Get a mutable reference to the object, if there is one. + pub fn obj_mut(&mut self) -> Option<&mut ServiceEventObject> + { + self.obj.as_mut().map(|x| x.0) + } + + /// Try to consume into the inner object. If there is no object, return self. + pub fn try_into_object(self) -> Result + { + match self.obj + { + Some(obj) => Ok(obj), + None => Err(self), + } + } +} + +impl From for Option +{ + #[inline] fn from(from: ServiceEvent) -> Self + { + from.obj + } +} + +impl TryFrom for ServiceEventObject +{ + type Error = NoObjectError; + + #[inline] fn try_from(from: ServiceEvent) -> Result + { + match from.obj + { + Some(obj) => Ok(obj.0), + None => Err(NoObjectError), + } + } +} + + +#[derive(Debug)] +/// Error returned from trying to extract an object from a `ServiceEvent` which has none. +pub struct NoObjectError; + +impl error::Error for NoObjectError{} +impl fmt::Display for NoObjectError +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "there was no object broadcasted along with this ") + } +} diff --git a/src/state/session.rs b/src/state/session.rs index 820fbd1..6aa8e1b 100644 --- a/src/state/session.rs +++ b/src/state/session.rs @@ -9,7 +9,7 @@ use tokio::{ task::JoinHandle, }; use std::sync::Arc; -use service::SubscribeError; +use crate::service::{self, SubscribeError}; id_type!(SessionID; "A unique session ID, not bound to a user."); @@ -121,25 +121,25 @@ impl Session } } -impl service::Service for Session -{ - type Message = SessionCommand; - type Response = SessionResponse; - - #[inline] fn wait_on(self) -> JoinHandle<()> { - self.handle - } - #[inline] fn message_in_ref(&self) -> &mpsc::Sender { - &self.tx - } - #[inline] fn message_in(&mut self) -> &mut mpsc::Sender { - &mut self.tx - } - #[inline] fn message_out(&mut self) -> &mut broadcast::Receiver { - &mut self.rx - } +// impl service::Service for Session +// { +// type Message = SessionCommand; +// type Response = SessionResponse; + +// #[inline] fn wait_on(self) -> JoinHandle<()> { +// self.handle +// } +// #[inline] fn message_in_ref(&self) -> &mpsc::Sender { +// &self.tx +// } +// #[inline] fn message_in(&mut self) -> &mut mpsc::Sender { +// &mut self.tx +// } +// #[inline] fn message_out(&mut self) -> &mut broadcast::Receiver { +// &mut self.rx +// } - #[inline] fn is_alive(&self) -> Option { - Some(Arc::strong_count(&self.meta) > 1) - } -} +// #[inline] fn is_alive(&self) -> Option { +// Some(Arc::strong_count(&self.meta) > 1) +// } +// }