The ffi module 73 While its scope is larger than mio (which only cares about non-blocking I/O), libuv is to Node in Java Script what mio is to Tokio in Rust. Note The reason for doing file I/O in a thread pool is that there have historically been poor cross-platform APIs for non-blocking file I/O. While it's true that many runtimes choose to relegate this task to a thread pool making blocking calls to the OS, it might not be true in the future as the OS APIs evolve over time. Creating a thread pool to handle these cases is outside the scope of this example (even mio considers this outside its scope, just to be clear). We'll focus on showing how epoll works and mention these topics in the text, even though we won't actually implement a solution for them in this example. Now that we've covered a lot of basic information about epoll, mio, and the design of our example, it's time to write some code and see for ourselves how this all works in practice. The ffi module Let's start with the modules that don't depend on any others and work our way from there. The ffi module contains mappings to the syscalls and data structures we need to communicate with the operating system. We'll also explain how epoll works in detail once we have presented the syscalls. It's only a few lines of code, so I'll place the first part here so it's easier to keep track of where we are in the file since there's quite a bit to explain. Open the ffi. rs file and write the following lines of code: ch04/a-epoll/src/ffi. rs pub const EPOLL_CTL_ADD: i32 = 1; pub const EPOLLIN: i32 = 0x1; pub const EPOLLET: i32 = 1 << 31; #[link(name = "c")] extern "C" { pub fn epoll_create(size: i32)-> i32; pub fn close(fd: i32)-> i32; pub fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut Event)-> i32; pub fn epoll_wait(epfd: i32, events: *mut Event, maxevents: i32, timeout: i32)-> i32; } The first thing you'll notice is that we declare a few constants called EPOLL_CTL_ADD, EPOLLIN, and EPOLLET.