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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
use crate::{ import::*, Addr, addr_inner::*, error::*, ActorInfo };


/// This is an address with similar functionality as [`Addr`], but it does not keep the
/// mailbox alive.
///
/// When using `send` or `call`, a [`ThesErr::MailboxClosed`] is returned
/// if no more strong addresses are around. The mailbox will still finish processing messages
/// already in the channel but [`WeakAddr`] will not accept any new messages.
//
pub struct WeakAddr< A: Actor >
{
	inner: AddrInner<A>,
}


impl< A: Actor > Clone for WeakAddr<A>
{
	fn clone( &self ) -> Self
	{
		let _s = self.info().span().entered();
		trace!( "CREATE WeakAddr" );

		Self
		{
			inner: self.inner.clone(),
		}
	}
}


/// Verify whether 2 Receivers will deliver to the same actor.
//
impl< A: Actor > PartialEq for WeakAddr<A>
{
	fn eq( &self, other: &Self ) -> bool
	{
		self.inner == other.inner
	}
}

impl< A: Actor > Eq for WeakAddr<A>{}



impl<A: Actor> fmt::Debug for WeakAddr<A>
{
	fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
	{
		let name = match &self.name().is_empty()
		{
			true  => String::new(),
			false => format!( ", {}", &self.name() )
		};

		write!
		(
			f                          ,
			"WeakAddr<{}> ~ {}{}"      ,
			std::any::type_name::<A>() ,
			&self.id()                 ,
			name                       ,
		)
	}
}



impl<A: Actor> fmt::Display for WeakAddr<A>
{
	fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
	{
		write!( f, "{} ({}, {})", self.inner.type_name(), self.id(), &self.name() )
	}
}




impl<A> WeakAddr<A> where A: Actor
{
	/// Create a strong address. This requires that there are still other
	/// strong addresses around at the time of this call, otherwise this will
	/// return [`ThesErr::MailboxClosed`].
	//
	pub fn strong( &self ) -> Result< Addr<A>, ThesErr >
	{
		Addr::try_from( self.inner.clone() )
	}


	/// Information about the actor: id, name, typename and a span for tracing.
	//
	pub fn info( &self ) -> Arc<ActorInfo>
	{
		self.inner.info.clone()
	}
}

// For debugging
//
impl<A: Actor> Drop for WeakAddr<A>
{
	fn drop( &mut self )
	{
		let _s = self.info().span().entered();
		trace!( "DROP WeakAddr" );
	}
}



impl<A, M> Address<M> for WeakAddr<A>

	where  A: Actor + Handler<M> ,
	       M: Message            ,

{
	fn call( &mut self, msg: M ) -> Return<'_, ThesRes< <M as Message>::Return >>
	{
		self.inner.call( msg )
	}



	fn clone_box( &self ) -> BoxAddress<M, ThesErr>
	{
		Box::new( self.clone() )
	}
}


impl<A> Identify for WeakAddr<A>

	where  A: Actor,

{
	/// Get the id of the mailbox this address sends to. There will be exactly one for each
	/// actor, so you can use this for uniquely identifying your actors.
	///
	/// This is an atomic usize that is incremented for every new mailbox. There currently
	/// is no overflow protection.
	//
	fn id( &self ) -> usize
	{
		self.inner.id()
	}

	fn name( &self ) -> Arc<str>
	{
		self.inner.name()
	}
}



impl<A, M> Sink<M> for WeakAddr<A>

	where A: Actor + Handler<M> ,
	      M: Message            ,

{
	type Error = ThesErr;

	fn poll_ready( mut self: Pin<&mut Self>, cx: &mut TaskContext<'_> ) -> Poll<Result<(), Self::Error>>
	{
		// There are no more strong addresses around, we no longer accept messages.
		//
		if self.inner.strong.lock().expect( "Mutex<StrongCount> poisoned" ).count() == 0
		{
			return Poll::Ready( Err( ThesErr::MailboxClosed{ info: self.inner.info.clone(), src: None } ) )
		}

		Pin::new( &mut self.inner ).poll_ready( cx )
	}


	fn start_send( mut self: Pin<&mut Self>, msg: M ) -> Result<(), Self::Error>
	{
		Pin::new( &mut self.inner ).start_send( msg )
	}


	fn poll_flush( mut self: Pin<&mut Self>, cx: &mut TaskContext<'_> ) -> Poll<Result<(), Self::Error>>
	{
		Pin::new( &mut self.inner ).poll_flush( cx )
	}


	/// This is a no-op. The address can only really close when dropped. Close has no meaning before that.
	//
	fn poll_close( mut self: Pin<&mut Self>, cx: &mut TaskContext<'_> ) -> Poll<Result<(), Self::Error>>
	{
		Pin::new( &mut self.inner ).poll_flush( cx )
	}
}


impl<A: Actor> From< AddrInner<A> > for WeakAddr<A>
{
	fn from( inner: AddrInner<A> ) -> Self
	{
		Self{ inner }
	}
}