1//! Functionality that is only available for `unix` platforms.
2
3#[cfg(not(async_io_no_io_safety))]
4use 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))]
45pub 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}
71