I have a TCP listener and am handling incoming connections. At some point, I want to stop the handling of incoming connections from another thread.
To do this, I followed the advice here which recommends to send a message to the thread that is iterating over .incoming()
.
I did this, and it works, but I'm concerned that the way I did it isn't optimal. Is it advisable to have a thread spinning like this. Are there any better ways to solve this problem?
Here is the code that implements the solution. Note the listener must be non-blocking for this to work or else the loop will hang on the tcp_iter.next()
line. Here, the loop is spinning most of the time checking if either the receiver or the incoming
iterator has something for it to process.
fn host_lobby(connections: Arc<Mutex<Vec<Connection>>>, receiver: Receiver<HaltMessage>) {
//receiver will indicated whether to kill the lobby.
println!("Started lobby!");
let address: SocketAddr = "127.0.0.1:12345"
.to_socket_addrs()
.unwrap()
.next()
.unwrap();
let listener = TcpListener::bind(address)
.map_err(|error| eprintln!("{:?}", error))
.unwrap();
listener.set_nonblocking(true);
println!("Listening on {}", listener.local_addr().unwrap());
let mut thread_handles: Vec<JoinHandle<()>> = Vec::new();
let mut tcp_iter = listener.incoming();
loop {
if let Ok(_) = receiver.try_recv() { //Received a stop
println!("Listener stopped");
break;
}
if let Some(Ok(stream)) = tcp_iter.next() { //if there is a new connection
println!("New connection!");
let connections_clone = Arc::clone(&connections); //moved to thread
thread_handles.push(
thread::spawn(move || {
handle_connection(stream, connections_clone)
})
);
}
}
}