diff --git a/src/os.rs b/src/os.rs index 5db3c57..7561849 100644 --- a/src/os.rs +++ b/src/os.rs @@ -1,5 +1,8 @@ //! Platform-specific functionality. +#[cfg(unix)] +pub mod unix; + #[cfg(any( target_os = "macos", target_os = "ios", diff --git a/src/os/unix.rs b/src/os/unix.rs new file mode 100644 index 0000000..ffb0832 --- /dev/null +++ b/src/os/unix.rs @@ -0,0 +1,70 @@ +//! Functionality that is only available for `unix` platforms. + +#[cfg(not(async_io_no_io_safety))] +use std::os::unix::io::BorrowedFd; + +/// Get a file descriptor that can be used to wait for readiness in an external runtime. +/// +/// This file descriptor is equivalent to the one used by the underlying epoll/kqueue/event ports +/// instance for polling. The intention is that this file descriptor can be registered into an +/// external runtime (like [`calloop`] or [GLib]) so that `async-io` can be seamlessly polled +/// alongside the other runtime. +/// +/// Not every backend used on `unix` has an associated file descriptor, however. While epoll, +/// kqueue and event ports have a file descriptor as a backend, on some Unix systems `async-io` +/// will use the `poll()` system call instead. Since there are no file descriptors intrinsically +/// associated with `poll()`, this function will return `None`. +/// +/// There is presently no way to stop the "`async-io`" thread from being launched, so the reactor +/// will still be continiously polled on that thread. This fact should be kept in mind by anyone +/// looking to integrate `async-io` into another runtime using this function. +/// +/// It is possible to use this function to call raw system calls on the underlying event source. +/// This is generally not recommended, since registered event sources may conflict with `async-io`'s +/// existing scheme for managing sources. The behavior resulting from this is not specified, but +/// will not result in undefined behavior. This could include panics, incorrect results, aborts, +/// memory leaks, and non-termination. +/// +/// [`calloop`]: https://docs.rs/calloop +/// [GLib]: https://en.wikipedia.org/wiki/GLib +/// +/// ## Example +/// +/// ``` +/// #![cfg(unix)] +/// +/// use async_io::os::unix::reactor_fd; +/// +/// my_runtime::register(reactor_fd().unwrap()); +/// # mod my_runtime { +/// # use std::os::unix::io::BorrowedFd; +/// # pub fn register(_: BorrowedFd<'_>) {} +/// # } +/// ``` +#[cfg(not(async_io_no_io_safety))] +pub fn reactor_fd() -> Option> { + cfg_if::cfg_if! { + if #[cfg(all( + any( + target_os = "linux", + target_os = "android", + target_os = "illumos", + target_os = "solaris", + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "watchos", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly", + ), + not(polling_test_poll_backend), + ))] { + use std::os::unix::io::AsFd; + Some(crate::Reactor::get().poller.as_fd()) + } else { + None + } + } +} diff --git a/src/reactor.rs b/src/reactor.rs index 40604e4..dda9f92 100644 --- a/src/reactor.rs +++ b/src/reactor.rs @@ -53,7 +53,7 @@ pub(crate) struct Reactor { /// Portable bindings to epoll/kqueue/event ports/IOCP. /// /// This is where I/O is polled, producing I/O events. - poller: Poller, + pub(crate) poller: Poller, /// Ticker bumped before polling. ///