cs431_homework/hello_server/tcp.rs
1//! TcpListener that can be cancelled.
2
3use std::io;
4use std::net::{TcpListener, TcpStream, ToSocketAddrs};
5use std::sync::atomic::{AtomicBool, Ordering};
6
7/// Like `std::net::tcp::TcpListener`, but `cancel`lable.
8#[derive(Debug)]
9pub struct CancellableTcpListener {
10 inner: TcpListener,
11
12 /// An atomic boolean flag that indicates if the listener is `cancel`led.
13 ///
14 /// NOTE: This can be safely read/written by multiple thread at the same time (note that its
15 /// methods take `&self` instead of `&mut self`). To set the flag, use `store` method with
16 /// `Ordering::Release`. To read the flag, use `load` method with `Ordering::Acquire`. We will
17 /// discuss their precise semantics later.
18 is_canceled: AtomicBool,
19}
20
21/// Like `std::net::tcp::Incoming`, but stops `accept`ing connections if the listener is `cancel`ed.
22#[derive(Debug)]
23pub struct Incoming<'a> {
24 listener: &'a CancellableTcpListener,
25}
26
27impl CancellableTcpListener {
28 /// Wraps `TcpListener::bind`.
29 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<CancellableTcpListener> {
30 let listener = TcpListener::bind(addr)?;
31 Ok(CancellableTcpListener {
32 inner: listener,
33 is_canceled: AtomicBool::new(false),
34 })
35 }
36
37 /// Signals the listener to stop accepting new connections.
38 pub fn cancel(&self) -> io::Result<()> {
39 // Set the flag first and make a bogus connection to itself to wake up the listener blocked
40 // in `accept`. Use `TcpListener::local_addr` and `TcpStream::connect`.
41 todo!()
42 }
43
44 /// Returns an iterator over the connections being received on this listener. The returned
45 /// iterator will return `None` if the listener is `cancel`led.
46 pub fn incoming(&self) -> Incoming<'_> {
47 Incoming { listener: self }
48 }
49}
50
51impl Iterator for Incoming<'_> {
52 type Item = io::Result<TcpStream>;
53 /// Returns None if the listener is `cancel()`led.
54 fn next(&mut self) -> Option<Self::Item> {
55 let stream = self.listener.inner.accept().map(|p| p.0);
56 todo!()
57 }
58}