-
Notifications
You must be signed in to change notification settings - Fork 667
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Epoll type #1882
Merged
Merged
Epoll type #1882
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,7 @@ use crate::errno::Errno; | |
use crate::Result; | ||
use libc::{self, c_int}; | ||
use std::mem; | ||
use std::os::unix::io::RawFd; | ||
use std::ptr; | ||
use std::os::unix::io::{FromRawFd,RawFd, OwnedFd, AsFd, AsRawFd}; | ||
|
||
libc_bitflags!( | ||
pub struct EpollFlags: c_int { | ||
|
@@ -70,20 +69,126 @@ impl EpollEvent { | |
} | ||
} | ||
|
||
/// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html). | ||
/// ``` | ||
/// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}}; | ||
/// # use nix::unistd::write; | ||
/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd}; | ||
/// # use std::time::{Instant, Duration}; | ||
/// # fn main() -> nix::Result<()> { | ||
/// const DATA: u64 = 17; | ||
/// const MILLIS: u64 = 100; | ||
/// | ||
/// // Create epoll | ||
/// let epoll = Epoll::new(EpollCreateFlags::empty())?; | ||
/// | ||
/// // Create eventfd & Add event | ||
/// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) }; | ||
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?; | ||
/// | ||
/// // Arm eventfd & Time wait | ||
/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?; | ||
/// let now = Instant::now(); | ||
/// | ||
/// // Wait on event | ||
/// let mut events = [EpollEvent::empty()]; | ||
/// epoll.wait(&mut events, MILLIS as isize)?; | ||
/// | ||
/// // Assert data correct & timeout didn't occur | ||
/// assert_eq!(events[0].data(), DATA); | ||
/// assert!(now.elapsed() < Duration::from_millis(MILLIS)); | ||
/// # Ok(()) | ||
/// # } | ||
/// ``` | ||
#[derive(Debug)] | ||
JonathanWoollett-Light marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub struct Epoll(pub OwnedFd); | ||
impl Epoll { | ||
/// Creates a new epoll instance and returns a file descriptor referring to that instance. | ||
/// | ||
/// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html). | ||
pub fn new(flags: EpollCreateFlags) -> Result<Self> { | ||
let res = unsafe { libc::epoll_create1(flags.bits()) }; | ||
let fd = Errno::result(res)?; | ||
let owned_fd = unsafe { OwnedFd::from_raw_fd(fd) }; | ||
Ok(Self(owned_fd)) | ||
} | ||
/// Add an entry to the interest list of the epoll file descriptor for | ||
/// specified in events. | ||
/// | ||
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`. | ||
pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> { | ||
self.epoll_ctl(EpollOp::EpollCtlAdd,fd,&mut event) | ||
} | ||
/// Remove (deregister) the target file descriptor `fd` from the interest list. | ||
/// | ||
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` . | ||
pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> { | ||
self.epoll_ctl(EpollOp::EpollCtlDel,fd,None) | ||
} | ||
/// Change the settings associated with `fd` in the interest list to the new settings specified | ||
/// in `event`. | ||
/// | ||
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`. | ||
pub fn modify<Fd: AsFd>(&self,fd: Fd, event: &mut EpollEvent) -> Result<()> { | ||
self.epoll_ctl(EpollOp::EpollCtlMod,fd,event) | ||
} | ||
/// Waits for I/O events, blocking the calling thread if no events are currently available. | ||
/// (This can be thought of as fetching items from the ready list of the epoll instance.) | ||
/// | ||
/// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html) | ||
pub fn wait(&self, events: &mut [EpollEvent], timeout: isize) -> Result<usize> { | ||
let res = unsafe { | ||
libc::epoll_wait( | ||
self.0.as_raw_fd(), | ||
events.as_mut_ptr() as *mut libc::epoll_event, | ||
events.len() as c_int, | ||
timeout as c_int, | ||
) | ||
}; | ||
|
||
Errno::result(res).map(|r| r as usize) | ||
} | ||
/// This system call is used to add, modify, or remove entries in the interest list of the epoll | ||
/// instance referred to by `self`. It requests that the operation `op` be performed for the | ||
/// target file descriptor, `fd`. | ||
/// | ||
/// When possible prefer [`Epoll::add`], [`Epoll::delete`] and [`Epoll::modify`]. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason to make this public? Any operation that can't be performed with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I'll make it private. |
||
/// | ||
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) | ||
fn epoll_ctl<'a, Fd: AsFd, T>( | ||
&self, | ||
op: EpollOp, | ||
fd: Fd, | ||
event: T, | ||
) -> Result<()> | ||
where | ||
T: Into<Option<&'a mut EpollEvent>>, | ||
{ | ||
let event: Option<&mut EpollEvent> = event.into(); | ||
let ptr = event.map(|x|&mut x.event as *mut libc::epoll_event).unwrap_or(std::ptr::null_mut()); | ||
unsafe { | ||
Errno::result(libc::epoll_ctl(self.0.as_raw_fd(), op as c_int, fd.as_fd().as_raw_fd(), ptr)).map(drop) | ||
} | ||
} | ||
} | ||
|
||
#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")] | ||
#[inline] | ||
pub fn epoll_create() -> Result<RawFd> { | ||
let res = unsafe { libc::epoll_create(1024) }; | ||
|
||
Errno::result(res) | ||
} | ||
|
||
#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")] | ||
#[inline] | ||
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> { | ||
let res = unsafe { libc::epoll_create1(flags.bits()) }; | ||
|
||
Errno::result(res) | ||
} | ||
|
||
#[deprecated(since = "0.27.0", note = "Use Epoll::epoll_ctl() instead")] | ||
#[inline] | ||
pub fn epoll_ctl<'a, T>( | ||
epfd: RawFd, | ||
|
@@ -102,13 +207,14 @@ where | |
if let Some(ref mut event) = event { | ||
libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) | ||
} else { | ||
libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut()) | ||
libc::epoll_ctl(epfd, op as c_int, fd, std::ptr::null_mut()) | ||
} | ||
}; | ||
Errno::result(res).map(drop) | ||
} | ||
} | ||
|
||
#[deprecated(since = "0.27.0", note = "Use Epoll::wait() instead")] | ||
#[inline] | ||
pub fn epoll_wait( | ||
epfd: RawFd, | ||
|
@@ -125,4 +231,4 @@ pub fn epoll_wait( | |
}; | ||
|
||
Errno::result(res).map(|r| r as usize) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to declare the
main()
function explicitly? If you leave it out, I think rustdoc will add it automatically.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rustdoc automatically adds
main() {}
without a return type. To use?
requires manually writing it with a return type.