1+ use futures:: channel:: mpsc;
2+ use futures:: { SinkExt , StreamExt } ;
13use std:: error:: Error ;
24use std:: fmt;
3- use tokio:: sync:: mpsc;
45
56/// An error returned when sending on a closed mailbox.
67///
78/// This error is returned by the asynchronous `send` method. It contains
89/// the message that could not be sent.
910#[ derive( Debug , PartialEq , Eq ) ]
10- pub struct SendError < T > ( pub T ) ;
11+ pub enum SendError {
12+ Closed ,
13+ }
1114
12- impl < T > fmt:: Display for SendError < T > {
15+ impl fmt:: Display for SendError {
1316 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1417 write ! ( f, "sending on a closed mailbox" )
1518 }
1619}
1720
18- impl < T : fmt:: Debug > Error for SendError < T > { }
19-
2021/// An error returned from the `try_send` method on a `Sender`.
2122#[ derive( Debug , PartialEq , Eq ) ]
2223pub enum TrySendError < T > {
@@ -37,14 +38,6 @@ impl<T> fmt::Display for TrySendError<T> {
3738
3839impl < T : fmt:: Debug > Error for TrySendError < T > { }
3940
40- // For convenience, we can convert a SendError into a TrySendError,
41- // as a 'Closed' state is a subset of 'TrySend' failures.
42- impl < T > From < SendError < T > > for TrySendError < T > {
43- fn from ( err : SendError < T > ) -> Self {
44- TrySendError :: Closed ( err. 0 )
45- }
46- }
47-
4841/// A handle to send messages to an actor's mailbox.
4942pub struct Sender < T > {
5043 sender : mpsc:: Sender < T > ,
@@ -62,22 +55,25 @@ impl<T> Sender<T> {
6255 /// Sends a message asynchronously, waiting if the mailbox is full.
6356 ///
6457 /// Returns a `SendError` only if the receiving actor has terminated.
65- pub async fn send ( & self , message : T ) -> Result < ( ) , SendError < T > > {
66- self . sender . send ( message) . await . map_err ( |e| SendError ( e. 0 ) )
58+ pub async fn send ( & mut self , message : T ) -> Result < ( ) , SendError > {
59+ self . sender
60+ . send ( message)
61+ . await
62+ . map_err ( |_e| SendError :: Closed )
6763 }
6864
6965 /// Attempts to immediately send a message.
7066 ///
7167 /// Returns a `TrySendError` if the mailbox is full or if the
7268 /// receiving actor has terminated.
73- pub fn try_send ( & self , message : T ) -> Result < ( ) , TrySendError < T > > {
74- use mpsc:: error:: TrySendError as TokioTrySendError ;
75- self . sender . try_send ( message) . map_err ( |e| match e {
76- TokioTrySendError :: Full ( m) => {
69+ pub fn try_send ( & mut self , message : T ) -> Result < ( ) , TrySendError < T > > {
70+ self . sender . try_send ( message) . map_err ( |e| {
71+ if e. is_disconnected ( ) {
72+ TrySendError :: Closed ( e. into_inner ( ) )
73+ } else {
7774 tracing:: info!( "try_send dropped a packet due to full queue" ) ;
78- TrySendError :: Full ( m )
75+ TrySendError :: Full ( e . into_inner ( ) )
7976 }
80- TokioTrySendError :: Closed ( m) => TrySendError :: Closed ( m) ,
8177 } )
8278 }
8379}
@@ -90,7 +86,7 @@ pub struct Receiver<T> {
9086impl < T > Receiver < T > {
9187 /// Receives the next message from the mailbox.
9288 pub async fn recv ( & mut self ) -> Option < T > {
93- self . receiver . recv ( ) . await
89+ self . receiver . next ( ) . await
9490 }
9591}
9692
@@ -107,7 +103,7 @@ mod tests {
107103
108104 #[ tokio:: test]
109105 async fn send_and_recv_single_message ( ) {
110- let ( sender, mut mailbox) = mailbox:: new ( 10 ) ;
106+ let ( mut sender, mut mailbox) = mailbox:: new ( 10 ) ;
111107 let message = "hello" . to_string ( ) ;
112108
113109 sender. send ( message. clone ( ) ) . await . unwrap ( ) ;
@@ -118,7 +114,7 @@ mod tests {
118114
119115 #[ tokio:: test]
120116 async fn recv_returns_none_when_all_senders_are_dropped ( ) {
121- let ( sender, mut mailbox) = mailbox:: new :: < i32 > ( 10 ) ;
117+ let ( mut sender, mut mailbox) = mailbox:: new :: < i32 > ( 10 ) ;
122118 sender. send ( 1 ) . await . unwrap ( ) ;
123119 sender. send ( 2 ) . await . unwrap ( ) ;
124120
@@ -135,7 +131,7 @@ mod tests {
135131
136132 #[ tokio:: test]
137133 async fn async_send_fails_when_receiver_is_dropped ( ) {
138- let ( sender, mailbox) = mailbox:: new :: < String > ( 10 ) ;
134+ let ( mut sender, mailbox) = mailbox:: new :: < String > ( 10 ) ;
139135
140136 // Drop the mailbox immediately
141137 drop ( mailbox) ;
@@ -144,27 +140,27 @@ mod tests {
144140 assert ! ( result. is_err( ) ) ;
145141
146142 // Check that the error is our custom SendError and we can get the message back
147- if let Err ( mailbox:: SendError ( msg) ) = result {
148- assert_eq ! ( msg, "should fail" ) ;
143+ if let Err ( mailbox:: SendError :: Closed ) = result {
149144 } else {
150145 panic ! ( "Expected a SendError" ) ;
151146 }
152147 }
153148
154149 #[ test]
155150 fn try_send_success_on_capacity ( ) {
156- let ( sender, _mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
151+ let ( mut sender, _mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
157152 let result = sender. try_send ( 123 ) ;
158153 assert ! ( result. is_ok( ) ) ;
159154 }
160155
161156 #[ test]
162157 fn try_send_fails_when_full ( ) {
163158 // Create a mailbox with a buffer of 1
164- let ( sender, _mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
159+ let ( mut sender, _mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
165160
166161 // The first send succeeds and fills the buffer
167162 sender. try_send ( 1 ) . unwrap ( ) ;
163+ sender. try_send ( 1 ) . unwrap ( ) ;
168164
169165 // The second send should fail because the buffer is full
170166 let result = sender. try_send ( 2 ) ;
@@ -179,7 +175,7 @@ mod tests {
179175
180176 #[ test]
181177 fn try_send_fails_when_receiver_is_dropped ( ) {
182- let ( sender, mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
178+ let ( mut sender, mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
183179
184180 // Drop the receiver
185181 drop ( mailbox) ;
@@ -196,14 +192,14 @@ mod tests {
196192
197193 #[ tokio:: test]
198194 async fn async_send_waits_when_full ( ) {
199- let ( sender, mut mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
195+ let ( mut sender, mut mailbox) = mailbox:: new :: < i32 > ( 1 ) ;
200196
201197 // Fill the buffer
202198 sender. send ( 1 ) . await . unwrap ( ) ;
203199
204200 // This send should wait. We spawn it in a separate task.
205201 let send_task = tokio:: spawn ( {
206- let sender = sender. clone ( ) ;
202+ let mut sender = sender. clone ( ) ;
207203 async move {
208204 sender. send ( 2 ) . await . unwrap ( ) ;
209205 }
@@ -227,8 +223,8 @@ mod tests {
227223
228224 #[ tokio:: test]
229225 async fn cloned_sender_works_and_channel_stays_open ( ) {
230- let ( sender1, mut mailbox) = mailbox:: new :: < i32 > ( 10 ) ;
231- let sender2 = sender1. clone ( ) ;
226+ let ( mut sender1, mut mailbox) = mailbox:: new :: < i32 > ( 10 ) ;
227+ let mut sender2 = sender1. clone ( ) ;
232228
233229 sender1. send ( 1 ) . await . unwrap ( ) ;
234230 sender2. send ( 2 ) . await . unwrap ( ) ;
0 commit comments