From b5dde3852ad5db1b6e532ae8dd82cedc1deb95e2 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 14 Feb 2023 21:24:05 +0000 Subject: [PATCH] feat: EventFd type --- CHANGELOG.md | 2 ++ src/sys/epoll.rs | 6 ++--- src/sys/eventfd.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8bde843f1..4663d29422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). - Added `mq_timedreceive` to `::nix::mqueue`. ([#1966])(https://github.com/nix-rust/nix/pull/1966) - Added `LocalPeerPid` to `nix::sys::socket::sockopt` for macOS. ([#1967](https://github.com/nix-rust/nix/pull/1967)) + - Added `EventFd` type. + ([#1945](https://github.com/nix-rust/nix/pull/1945)) ### Changed diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 36f9c17d0e..e7f9f89a0b 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, AsRawFd, 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.as_raw_fd(), &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..bf3a96242a 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.as_raw_fd(),&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.as_raw_fd(),&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.as_raw_fd(),&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