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}