use std::{ ops::Deref, os::unix::io::{ AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd, }, sync::atomic::{ AtomicBool, Ordering, }, }; use inotify_sys as ffi; /// A RAII guard around a `RawFd` that closes it automatically on drop. #[derive(Debug)] pub struct FdGuard { pub(crate) fd : RawFd, pub(crate) close_on_drop: AtomicBool, } impl FdGuard { /// Indicate that the wrapped file descriptor should _not_ be closed /// when the guard is dropped. /// /// This should be called in cases where ownership of the wrapped file /// descriptor has been "moved" out of the guard. /// /// This is factored out into a separate function to ensure that it's /// always used consistently. #[inline] pub fn should_not_close(&self) { self.close_on_drop.store(false, Ordering::Release); } } impl Deref for FdGuard { type Target = RawFd; #[inline] fn deref(&self) -> &Self::Target { &self.fd } } impl Drop for FdGuard { fn drop(&mut self) { if self.close_on_drop.load(Ordering::Acquire) { unsafe { ffi::close(self.fd); } } } } impl FromRawFd for FdGuard { unsafe fn from_raw_fd(fd: RawFd) -> Self { FdGuard { fd, close_on_drop: AtomicBool::new(true), } } } impl IntoRawFd for FdGuard { fn into_raw_fd(self) -> RawFd { self.should_not_close(); self.fd } } impl AsRawFd for FdGuard { fn as_raw_fd(&self) -> RawFd { self.fd } } impl AsFd for FdGuard { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(self.fd) } } } impl PartialEq for FdGuard { fn eq(&self, other: &FdGuard) -> bool { self.fd == other.fd } }