Skip to content

Commit

Permalink
Breaking change: support creating an Async with AsFd rather than …
Browse files Browse the repository at this point in the history
…`AsRawFd`

Modify the `Async::new` constructor to use `AsFd` rather than `AsRawFd`
(or the socket equivalents on Windows). Modify other code accordingly.
Drop impls of `AsRawFd` and `AsRawSocket`.

Update inotify dev-dependency to 0.10.1 so that the inotify example
still builds.
  • Loading branch information
joshtriplett committed Jun 7, 2023
1 parent 090ee6b commit b745565
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ signal-hook = "0.3"
tempfile = "3"

[target.'cfg(target_os = "linux")'.dev-dependencies]
inotify = { version = "0.10", default-features = false }
inotify = { version = "0.10.1", default-features = false }
timerfd = "1"

[target.'cfg(windows)'.dev-dependencies]
Expand Down
10 changes: 8 additions & 2 deletions examples/unix-signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@
#[cfg(unix)]
fn main() -> std::io::Result<()> {
use std::os::unix::{io::AsRawFd, net::UnixStream};
use std::os::unix::{
io::{AsFd, AsRawFd},
net::UnixStream,
};

use async_io::Async;
use futures_lite::{future, prelude::*};

future::block_on(async {
// Create a Unix stream that receives a byte on each signal occurrence.
let (a, mut b) = Async::<UnixStream>::pair()?;
signal_hook::low_level::pipe::register_raw(signal_hook::consts::SIGINT, a.as_raw_fd())?;
signal_hook::low_level::pipe::register_raw(
signal_hook::consts::SIGINT,
a.as_fd().as_raw_fd(),
)?;
println!("Waiting for Ctrl-C...");

// Receive a byte that indicates the Ctrl-C signal occurred.
Expand Down
46 changes: 13 additions & 33 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ use std::time::{Duration, Instant};

#[cfg(unix)]
use std::{
os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd},
os::unix::net::{SocketAddr as UnixSocketAddr, UnixDatagram, UnixListener, UnixStream},
path::Path,
};
Expand Down Expand Up @@ -621,14 +621,14 @@ pub struct Async<T> {
impl<T> Unpin for Async<T> {}

#[cfg(unix)]
impl<T: AsRawFd> Async<T> {
impl<T: AsFd> Async<T> {
/// Creates an async I/O handle.
///
/// This method will put the handle in non-blocking mode and register it in
/// [epoll]/[kqueue]/[event ports]/[IOCP].
///
/// On Unix systems, the handle must implement `AsRawFd`, while on Windows it must implement
/// `AsRawSocket`.
/// On Unix systems, the handle must implement `AsFd`, while on Windows it must implement
/// `AsSocket`.
///
/// [epoll]: https://en.wikipedia.org/wiki/Epoll
/// [kqueue]: https://en.wikipedia.org/wiki/Kqueue
Expand All @@ -647,14 +647,9 @@ impl<T: AsRawFd> Async<T> {
/// # std::io::Result::Ok(()) });
/// ```
pub fn new(io: T) -> io::Result<Async<T>> {
let raw = io.as_raw_fd();
let fd = io.as_fd();

// Put the file descriptor in non-blocking mode.
//
// Safety: We assume `as_raw_fd()` returns a valid fd. When we can
// depend on Rust >= 1.63, where `AsFd` is stabilized, and when
// `TimerFd` implements it, we can remove this unsafe and simplify this.
let fd = unsafe { rustix::fd::BorrowedFd::borrow_raw(raw) };
cfg_if::cfg_if! {
// ioctl(FIONBIO) sets the flag atomically, but we use this only on Linux
// for now, as with the standard library, because it seems to behave
Expand All @@ -674,19 +669,12 @@ impl<T: AsRawFd> Async<T> {
}

Ok(Async {
source: Reactor::get().insert_io(raw)?,
source: Reactor::get().insert_io(fd.as_raw_fd())?,
io: Some(io),
})
}
}

#[cfg(unix)]
impl<T: AsRawFd> AsRawFd for Async<T> {
fn as_raw_fd(&self) -> RawFd {
self.get_ref().as_raw_fd()
}
}

#[cfg(unix)]
impl<T: AsFd> AsFd for Async<T> {
fn as_fd(&self) -> BorrowedFd<'_> {
Expand All @@ -695,7 +683,7 @@ impl<T: AsFd> AsFd for Async<T> {
}

#[cfg(unix)]
impl<T: AsRawFd + From<OwnedFd>> TryFrom<OwnedFd> for Async<T> {
impl<T: AsFd + From<OwnedFd>> TryFrom<OwnedFd> for Async<T> {
type Error = io::Error;

fn try_from(value: OwnedFd) -> Result<Self, Self::Error> {
Expand All @@ -713,14 +701,14 @@ impl<T: Into<OwnedFd>> TryFrom<Async<T>> for OwnedFd {
}

#[cfg(windows)]
impl<T: AsRawSocket> Async<T> {
impl<T: AsSocket> Async<T> {
/// Creates an async I/O handle.
///
/// This method will put the handle in non-blocking mode and register it in
/// [epoll]/[kqueue]/[event ports]/[IOCP].
///
/// On Unix systems, the handle must implement `AsRawFd`, while on Windows it must implement
/// `AsRawSocket`.
/// On Unix systems, the handle must implement `AsFd`, while on Windows it must implement
/// `AsSocket`.
///
/// [epoll]: https://en.wikipedia.org/wiki/Epoll
/// [kqueue]: https://en.wikipedia.org/wiki/Kqueue
Expand All @@ -739,8 +727,7 @@ impl<T: AsRawSocket> Async<T> {
/// # std::io::Result::Ok(()) });
/// ```
pub fn new(io: T) -> io::Result<Async<T>> {
let sock = io.as_raw_socket();
let borrowed = unsafe { rustix::fd::BorrowedFd::borrow_raw(sock) };
let borrowed = io.as_socket();

// Put the socket in non-blocking mode.
//
Expand All @@ -750,19 +737,12 @@ impl<T: AsRawSocket> Async<T> {
rustix::io::ioctl_fionbio(borrowed, true)?;

Ok(Async {
source: Reactor::get().insert_io(sock)?,
source: Reactor::get().insert_io(borrowed.as_raw_socket())?,
io: Some(io),
})
}
}

#[cfg(windows)]
impl<T: AsRawSocket> AsRawSocket for Async<T> {
fn as_raw_socket(&self) -> RawSocket {
self.get_ref().as_raw_socket()
}
}

#[cfg(windows)]
impl<T: AsSocket> AsSocket for Async<T> {
fn as_socket(&self) -> BorrowedSocket<'_> {
Expand All @@ -771,7 +751,7 @@ impl<T: AsSocket> AsSocket for Async<T> {
}

#[cfg(windows)]
impl<T: AsRawSocket + From<OwnedSocket>> TryFrom<OwnedSocket> for Async<T> {
impl<T: AsSocket + From<OwnedSocket>> TryFrom<OwnedSocket> for Async<T> {
type Error = io::Error;

fn try_from(value: OwnedSocket) -> Result<Self, Self::Error> {
Expand Down

0 comments on commit b745565

Please sign in to comment.