1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
// Copyright (c) Sean Lawlor
//
// This source code is licensed under both the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree.
//! [ActorRef] is a strongly-typed wrapper over an [ActorCell]
use std::any::TypeId;
use std::marker::PhantomData;
use crate::{ActorName, Message, MessagingErr, SupervisionEvent};
use super::ActorCell;
/// An [ActorRef] is a strongly-typed wrapper over an [ActorCell]
/// to provide some syntactic wrapping on the requirement to pass
/// the actor's message type everywhere.
///
/// An [ActorRef] is the primary means of communication typically used
/// when interfacing with [super::Actor]s
///
/// The [ActorRef] is SPECIFICALLY marked [Sync], regardless of the message type
/// because all usages of the message type are to send an owned instance of a message
/// and in no case is that message instance shared across threads. This is guaranteed
/// by the underlying Tokio channel usages. Without this manual marking of [Sync] on
/// [ActorRef], we would need to constrain the message type [Message] to be [Sync] which
/// is overly restrictive.
pub struct ActorRef<TMessage> {
pub(crate) inner: ActorCell,
_tactor: PhantomData<TMessage>,
}
unsafe impl<T> Sync for ActorRef<T> {}
impl<TMessage> Clone for ActorRef<TMessage> {
fn clone(&self) -> Self {
ActorRef {
inner: self.inner.clone(),
_tactor: PhantomData::<TMessage>,
}
}
}
impl<TMessage> std::ops::Deref for ActorRef<TMessage> {
type Target = ActorCell;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<TMessage> From<ActorCell> for ActorRef<TMessage> {
fn from(value: ActorCell) -> Self {
Self {
inner: value,
_tactor: PhantomData::<TMessage>,
}
}
}
impl<TActor> From<ActorRef<TActor>> for ActorCell {
fn from(value: ActorRef<TActor>) -> Self {
value.inner
}
}
impl<TMessage> std::fmt::Debug for ActorRef<TMessage> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.inner)
}
}
impl<TMessage> ActorRef<TMessage> {
/// Retrieve a cloned [ActorCell] representing this [ActorRef]
pub fn get_cell(&self) -> ActorCell {
self.inner.clone()
}
/// Notify the supervisor and all monitors that a supervision event occurred.
/// Monitors receive a reduced copy of the supervision event which won't contain
/// the [crate::actor::BoxedState] and collapses the [crate::ActorProcessingErr]
/// exception to a [String]
///
/// * `evt` - The event to send to this [crate::Actor]'s supervisors
pub fn notify_supervisor_and_monitors(&self, evt: SupervisionEvent) {
self.inner.notify_supervisor_and_monitors(evt)
}
}
impl<TMessage> crate::actor::ActorRef<TMessage>
where
TMessage: Message,
{
/// Send a strongly-typed message, constructing the boxed message on the fly
///
/// * `message` - The message to send
///
/// Returns [Ok(())] on successful message send, [Err(MessagingErr)] otherwise
pub fn send_message(&self, message: TMessage) -> Result<(), MessagingErr<TMessage>> {
self.inner.send_message::<TMessage>(message)
}
// ========================== General Actor Operation Aliases ========================== //
// -------------------------- ActorRegistry -------------------------- //
/// Try and retrieve a strongly-typed actor from the registry.
///
/// Alias of [crate::registry::where_is]
pub fn where_is(name: ActorName) -> Option<crate::actor::ActorRef<TMessage>> {
if let Some(actor) = crate::registry::where_is(name) {
// check the type id when pulling from the registry
if actor.get_type_id() == TypeId::of::<TMessage>() {
Some(actor.into())
} else {
None
}
} else {
None
}
}
}