diff --git a/changelog/1945.added.md b/changelog/1945.added.md new file mode 100644 index 0000000000..19bea06715 --- /dev/null +++ b/changelog/1945.added.md @@ -0,0 +1 @@ +Added `EventFd` type. \ No newline at end of file diff --git a/changelog/1945.changed.md b/changelog/1945.changed.md new file mode 100644 index 0000000000..145d9287b8 --- /dev/null +++ b/changelog/1945.changed.md @@ -0,0 +1 @@ +Deprecated `sys::eventfd::eventfd`. \ No newline at end of file diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 679f9c47d1..5c973f54e9 100644 --- a/src/sys/epoll.rs +++ b/src/sys/epoll.rs @@ -71,7 +71,7 @@ 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::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{EventFd, EfdFlags}}; /// # use nix::unistd::write; /// # use std::os::unix::io::{OwnedFd, FromRawFd, AsFd}; /// # use std::time::{Instant, Duration}; @@ -83,11 +83,11 @@ impl EpollEvent { /// let epoll = Epoll::new(EpollCreateFlags::empty())?; /// /// // Create eventfd & Add event -/// let eventfd = eventfd(0, EfdFlags::empty())?; +/// let eventfd = EventFd::new()?; /// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?; /// /// // Arm eventfd & Time wait -/// write(&eventfd, &1u64.to_ne_bytes())?; +/// eventfd.arm()?; /// let now = Instant::now(); /// /// // Wait on event diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs index f1723519cf..0f456cf67e 100644 --- a/src/sys/eventfd.rs +++ b/src/sys/eventfd.rs @@ -1,6 +1,6 @@ use crate::errno::Errno; -use crate::Result; -use std::os::unix::io::{FromRawFd, OwnedFd}; +use crate::{Result,unistd}; +use std::os::unix::io::{FromRawFd, OwnedFd, AsRawFd, AsFd, RawFd, BorrowedFd}; libc_bitflags! { pub struct EfdFlags: libc::c_int { @@ -10,8 +10,69 @@ libc_bitflags! { } } +#[deprecated(since = "0.27.0", note = "Use EventFd::from_value_and_flags() instead")] pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result { let res = unsafe { libc::eventfd(initval, flags.bits()) }; Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) }) } + +#[derive(Debug)] +pub struct EventFd(pub OwnedFd); +impl EventFd { + /// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`. + pub fn new() -> Result { + Self::from_value_and_flags(0, EfdFlags::empty()) + } + /// Constructs [`EventFd`] with the given `init_val` and `flags`. + /// + /// Wrapper around [`libc::eventfd`]. + pub fn from_value_and_flags(init_val: u32, flags: EfdFlags) -> Result { + let res = unsafe { libc::eventfd(init_val, flags.bits()) }; + Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) })) + } + /// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`. + pub fn from_flags(flags: EfdFlags) -> Result { + Self::from_value_and_flags(0, flags) + } + /// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`. + pub fn from_value(init_val: u32) -> Result { + Self::from_value_and_flags(init_val, EfdFlags::empty()) + } + /// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately. + /// + /// [`EventFd::write`] with `1`. + pub fn arm(&self) -> Result { + unistd::write(&self.0,&1u64.to_ne_bytes()) + } + /// Defuses `self`, a following call to `poll`, `select` or `epoll` will block. + /// + /// [`EventFd::write`] with `0`. + pub fn defuse(&self) -> Result { + unistd::write(&self.0,&0u64.to_ne_bytes()) + } + /// Enqueues `value` triggers. + /// + /// The next `value` calls to `poll`, `select` or `epoll` will return immediately. + /// + /// [`EventFd::write`] with `value`. + pub fn write(&self, value: u64) -> Result { + unistd::write(&self.0,&value.to_ne_bytes()) + } + // Reads the value from the file descriptor. + pub fn read(&self) -> Result { + let mut arr = [0; std::mem::size_of::()]; + unistd::read(self.0.as_raw_fd(),&mut arr)?; + Ok(u64::from_ne_bytes(arr)) + } +} +impl AsFd for EventFd { + fn as_fd(&self) -> BorrowedFd { + self.0.as_fd() + } +} +impl AsRawFd for EventFd { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} \ No newline at end of file