Skip to content

Commit 524df87

Browse files
authored
feat: Add a way to get the global poller's file descriptor
Makes it easier to register the global poller into another event loop.
1 parent eb98b47 commit 524df87

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

src/os.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Platform-specific functionality.
22
3+
#[cfg(unix)]
4+
pub mod unix;
5+
36
#[cfg(any(
47
target_os = "macos",
58
target_os = "ios",

src/os/unix.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//! Functionality that is only available for `unix` platforms.
2+
3+
#[cfg(not(async_io_no_io_safety))]
4+
use std::os::unix::io::BorrowedFd;
5+
6+
/// Get a file descriptor that can be used to wait for readiness in an external runtime.
7+
///
8+
/// This file descriptor is equivalent to the one used by the underlying epoll/kqueue/event ports
9+
/// instance for polling. The intention is that this file descriptor can be registered into an
10+
/// external runtime (like [`calloop`] or [GLib]) so that `async-io` can be seamlessly polled
11+
/// alongside the other runtime.
12+
///
13+
/// Not every backend used on `unix` has an associated file descriptor, however. While epoll,
14+
/// kqueue and event ports have a file descriptor as a backend, on some Unix systems `async-io`
15+
/// will use the `poll()` system call instead. Since there are no file descriptors intrinsically
16+
/// associated with `poll()`, this function will return `None`.
17+
///
18+
/// There is presently no way to stop the "`async-io`" thread from being launched, so the reactor
19+
/// will still be continiously polled on that thread. This fact should be kept in mind by anyone
20+
/// looking to integrate `async-io` into another runtime using this function.
21+
///
22+
/// It is possible to use this function to call raw system calls on the underlying event source.
23+
/// This is generally not recommended, since registered event sources may conflict with `async-io`'s
24+
/// existing scheme for managing sources. The behavior resulting from this is not specified, but
25+
/// will not result in undefined behavior. This could include panics, incorrect results, aborts,
26+
/// memory leaks, and non-termination.
27+
///
28+
/// [`calloop`]: https://docs.rs/calloop
29+
/// [GLib]: https://en.wikipedia.org/wiki/GLib
30+
///
31+
/// ## Example
32+
///
33+
/// ```
34+
/// #![cfg(unix)]
35+
///
36+
/// use async_io::os::unix::reactor_fd;
37+
///
38+
/// my_runtime::register(reactor_fd().unwrap());
39+
/// # mod my_runtime {
40+
/// # use std::os::unix::io::BorrowedFd;
41+
/// # pub fn register(_: BorrowedFd<'_>) {}
42+
/// # }
43+
/// ```
44+
#[cfg(not(async_io_no_io_safety))]
45+
pub fn reactor_fd() -> Option<BorrowedFd<'static>> {
46+
cfg_if::cfg_if! {
47+
if #[cfg(all(
48+
any(
49+
target_os = "linux",
50+
target_os = "android",
51+
target_os = "illumos",
52+
target_os = "solaris",
53+
target_os = "macos",
54+
target_os = "ios",
55+
target_os = "tvos",
56+
target_os = "watchos",
57+
target_os = "freebsd",
58+
target_os = "netbsd",
59+
target_os = "openbsd",
60+
target_os = "dragonfly",
61+
),
62+
not(polling_test_poll_backend),
63+
))] {
64+
use std::os::unix::io::AsFd;
65+
Some(crate::Reactor::get().poller.as_fd())
66+
} else {
67+
None
68+
}
69+
}
70+
}

src/reactor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub(crate) struct Reactor {
5353
/// Portable bindings to epoll/kqueue/event ports/IOCP.
5454
///
5555
/// This is where I/O is polled, producing I/O events.
56-
poller: Poller,
56+
pub(crate) poller: Poller,
5757

5858
/// Ticker bumped before polling.
5959
///

0 commit comments

Comments
 (0)