Step 1 - Setting the O_NONBLOCK Flag

The first step to asynchronous I/O is to change the I/O handle to be nonblocking by setting the O_NONBLOCK flag.

API

Async::new(handle) is responsible for setting the I/O handle to be nonblocking.

Implementation

Async::new(handle) is the constructor of the Async struct. For example, here is how you create an instance of Async<TcpListener>:

#![allow(unused)]
fn main() {
let listener = TcpListener::bind(addr)?;
Async::new(listener);
}

Here is the implementation of Async::new:

#![allow(unused)]
fn main() {
impl<T: AsRawFd> Async<T> {
    pub fn new(io: T) -> io::Result<Async<T>> {
        Ok(Async {
            source: get_reactor().create_source(io.as_raw_fd()),
            io: Some(Box::new(io)),
        })
    }
}
}

The get_reactor() method retrieves the Reactor for the executor running on the current thread. The create_source method, as shown below, sets the O_NONBLOCK flag for the handle with fcntl.

#![allow(unused)]
fn main() {
impl Reactor {
	...
	pub fn create_source(&self, raw: RawFd) -> Source {
      fcntl(raw, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap();
      self.new_source(raw, SourceType::PollableFd)
  }

	fn new_source(&self, raw: RawFd, stype: SourceType) -> Source {
        Source::new(raw, stype, None)
    }

}
}