@@ -9,6 +9,7 @@ use std::{
9
9
use futures:: {
10
10
channel:: mpsc,
11
11
SinkExt ,
12
+ select,
12
13
} ;
13
14
14
15
use async_std:: {
@@ -22,6 +23,8 @@ type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>
22
23
type Sender < T > = mpsc:: UnboundedSender < T > ;
23
24
type Receiver < T > = mpsc:: UnboundedReceiver < T > ;
24
25
26
+ #[ derive( Debug ) ]
27
+ enum Void { }
25
28
26
29
fn main ( ) -> Result < ( ) > {
27
30
task:: block_on ( server ( "127.0.0.1:8080" ) )
@@ -38,7 +41,8 @@ async fn server(addr: impl ToSocketAddrs) -> Result<()> {
38
41
println ! ( "Accepting from: {}" , stream. peer_addr( ) ?) ;
39
42
spawn_and_log_error ( client ( broker_sender. clone ( ) , stream) ) ;
40
43
}
41
- broker. await ?;
44
+ drop ( broker_sender) ;
45
+ broker. await ;
42
46
Ok ( ( ) )
43
47
}
44
48
@@ -51,7 +55,12 @@ async fn client(mut broker: Sender<Event>, stream: TcpStream) -> Result<()> {
51
55
None => Err ( "peer disconnected immediately" ) ?,
52
56
Some ( line) => line?,
53
57
} ;
54
- broker. send ( Event :: NewPeer { name : name. clone ( ) , stream : Arc :: clone ( & stream) } ) . await . unwrap ( ) ;
58
+ let ( _shutdown_sender, shutdown_receiver) = mpsc:: unbounded :: < Void > ( ) ;
59
+ broker. send ( Event :: NewPeer {
60
+ name : name. clone ( ) ,
61
+ stream : Arc :: clone ( & stream) ,
62
+ shutdown : shutdown_receiver,
63
+ } ) . await . unwrap ( ) ;
55
64
56
65
while let Some ( line) = lines. next ( ) . await {
57
66
let line = line?;
@@ -68,16 +77,27 @@ async fn client(mut broker: Sender<Event>, stream: TcpStream) -> Result<()> {
68
77
msg,
69
78
} ) . await . unwrap ( ) ;
70
79
}
80
+
71
81
Ok ( ( ) )
72
82
}
73
83
74
84
async fn client_writer (
75
- mut messages : Receiver < String > ,
85
+ messages : & mut Receiver < String > ,
76
86
stream : Arc < TcpStream > ,
87
+ mut shutdown : Receiver < Void > ,
77
88
) -> Result < ( ) > {
78
89
let mut stream = & * stream;
79
- while let Some ( msg) = messages. next ( ) . await {
80
- stream. write_all ( msg. as_bytes ( ) ) . await ?;
90
+ loop {
91
+ select ! {
92
+ msg = messages. next( ) => match msg {
93
+ Some ( msg) => stream. write_all( msg. as_bytes( ) ) . await ?,
94
+ None => break ,
95
+ } ,
96
+ void = shutdown. next( ) => match void {
97
+ Some ( void) => match void { } ,
98
+ None => break ,
99
+ }
100
+ }
81
101
}
82
102
Ok ( ( ) )
83
103
}
@@ -87,6 +107,7 @@ enum Event {
87
107
NewPeer {
88
108
name : String ,
89
109
stream : Arc < TcpStream > ,
110
+ shutdown : Receiver < Void > ,
90
111
} ,
91
112
Message {
92
113
from : String ,
@@ -95,31 +116,54 @@ enum Event {
95
116
} ,
96
117
}
97
118
98
- async fn broker ( mut events : Receiver < Event > ) -> Result < ( ) > {
119
+ async fn broker ( mut events : Receiver < Event > ) {
120
+ let ( disconnect_sender, mut disconnect_receiver) =
121
+ mpsc:: unbounded :: < ( String , Receiver < String > ) > ( ) ;
99
122
let mut peers: HashMap < String , Sender < String > > = HashMap :: new ( ) ;
100
123
101
- while let Some ( event) = events. next ( ) . await {
124
+ loop {
125
+ let event = select ! {
126
+ event = events. next( ) => match event {
127
+ None => break ,
128
+ Some ( event) => event,
129
+ } ,
130
+ disconnect = disconnect_receiver. next( ) => {
131
+ let ( name, _pending_messages) = disconnect. unwrap( ) ;
132
+ assert!( peers. remove( & name) . is_some( ) ) ;
133
+ continue ;
134
+ } ,
135
+ } ;
102
136
match event {
103
137
Event :: Message { from, to, msg } => {
104
138
for addr in to {
105
139
if let Some ( peer) = peers. get_mut ( & addr) {
106
- peer. send ( format ! ( "from {}: {}\n " , from, msg) ) . await ?
140
+ peer. send ( format ! ( "from {}: {}\n " , from, msg) ) . await
141
+ . unwrap ( )
107
142
}
108
143
}
109
144
}
110
- Event :: NewPeer { name, stream} => {
111
- match peers. entry ( name) {
145
+ Event :: NewPeer { name, stream, shutdown } => {
146
+ match peers. entry ( name. clone ( ) ) {
112
147
Entry :: Occupied ( ..) => ( ) ,
113
148
Entry :: Vacant ( entry) => {
114
- let ( client_sender, client_receiver) = mpsc:: unbounded ( ) ;
149
+ let ( client_sender, mut client_receiver) = mpsc:: unbounded ( ) ;
115
150
entry. insert ( client_sender) ;
116
- spawn_and_log_error ( client_writer ( client_receiver, stream) ) ;
151
+ let mut disconnect_sender = disconnect_sender. clone ( ) ;
152
+ spawn_and_log_error ( async move {
153
+ let res = client_writer ( & mut client_receiver, stream, shutdown) . await ;
154
+ disconnect_sender. send ( ( name, client_receiver) ) . await
155
+ . unwrap ( ) ;
156
+ res
157
+ } ) ;
117
158
}
118
159
}
119
160
}
120
161
}
121
162
}
122
- Ok ( ( ) )
163
+ drop ( peers) ;
164
+ drop ( disconnect_sender) ;
165
+ while let Some ( ( _name, _pending_messages) ) = disconnect_receiver. next ( ) . await {
166
+ }
123
167
}
124
168
125
169
fn spawn_and_log_error < F > ( fut : F ) -> task:: JoinHandle < ( ) >
0 commit comments