tiny_actor/actor/
address.rs1use crate::*;
2use event_listener::EventListener;
3use futures::{Future, FutureExt};
4use std::{
5 fmt::Debug,
6 mem::ManuallyDrop,
7 pin::Pin,
8 sync::Arc,
9 task::{Context, Poll},
10};
11
12#[derive(Debug)]
23pub struct Address<C = dyn AnyChannel>
24where
25 C: DynChannel + ?Sized,
26{
27 channel: Arc<C>,
28 exit_listener: Option<EventListener>,
29}
30
31impl<C> Address<C>
32where
33 C: DynChannel + ?Sized,
34{
35 pub(crate) fn from_channel(channel: Arc<C>) -> Self {
37 Self {
38 channel,
39 exit_listener: None,
40 }
41 }
42
43 pub(crate) fn channel(&self) -> &Arc<C> {
44 &self.channel
45 }
46
47 fn into_parts(self) -> (Arc<C>, Option<EventListener>) {
48 let no_drop = ManuallyDrop::new(self);
49 unsafe {
50 let channel = std::ptr::read(&no_drop.channel);
51 let exit_listener = std::ptr::read(&no_drop.exit_listener);
52 (channel, exit_listener)
53 }
54 }
55
56 pub fn downcast<M: Send + 'static>(self) -> Result<Address<Channel<M>>, Self>
58 where
59 C: AnyChannel,
60 {
61 let (channel, exit_listener) = self.into_parts();
62 match channel.clone().into_any().downcast() {
63 Ok(channel) => Ok(Address {
64 channel,
65 exit_listener,
66 }),
67 Err(_) => Err(Self {
68 channel,
69 exit_listener,
70 }),
71 }
72 }
73
74 gen::dyn_channel_methods!();
75}
76
77impl<M> Address<Channel<M>> {
78 pub fn into_dyn(self) -> Address
80 where
81 M: Send + 'static,
82 {
83 let (channel, exit_listener) = self.into_parts();
84 Address {
85 channel,
86 exit_listener,
87 }
88 }
89
90 gen::send_methods!();
91}
92
93#[cfg(feature = "internals")]
94impl<C> Address<C>
95where
96 C: DynChannel + ?Sized,
97{
98 pub fn transform_channel<C2: DynChannel + ?Sized>(
99 self,
100 func: fn(Arc<C>) -> Arc<C2>,
101 ) -> Address<C2> {
102 let (channel, exit_listener) = self.into_parts();
103 Address {
104 channel: func(channel),
105 exit_listener,
106 }
107 }
108
109 pub fn channel_ref(&self) -> &C {
110 &self.channel
111 }
112}
113
114impl<C: DynChannel + ?Sized> Future for Address<C> {
115 type Output = ();
116
117 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
118 if self.channel.has_exited() {
119 Poll::Ready(())
120 } else {
121 if self.exit_listener.is_none() {
122 self.exit_listener = Some(self.channel.get_exit_listener())
123 }
124 if self.channel.has_exited() {
125 Poll::Ready(())
126 } else {
127 self.exit_listener.as_mut().unwrap().poll_unpin(cx)
128 }
129 }
130 }
131}
132
133impl<C: DynChannel + ?Sized> Unpin for Address<C> {}
134
135impl<C: DynChannel + ?Sized> Clone for Address<C> {
136 fn clone(&self) -> Self {
137 self.channel.add_address();
138 Self {
139 channel: self.channel.clone(),
140 exit_listener: None,
141 }
142 }
143}
144
145impl<C: DynChannel + ?Sized> Drop for Address<C> {
146 fn drop(&mut self) {
147 self.channel.remove_address();
148 }
149}