1use std::{
2 ops::Deref,
3 os::unix::io::{
4 AsRawFd,
5 FromRawFd,
6 IntoRawFd,
7 RawFd,
8 },
9 sync::atomic::{
10 AtomicBool,
11 Ordering,
12 },
13};
14
15use inotify_sys as ffi;
16
17
18/// A RAII guard around a `RawFd` that closes it automatically on drop.
19#[derive(Debug)]
20pub struct FdGuard {
21 pub(crate) fd : RawFd,
22 pub(crate) close_on_drop: AtomicBool,
23}
24
25impl FdGuard {
26
27 /// Indicate that the wrapped file descriptor should _not_ be closed
28 /// when the guard is dropped.
29 ///
30 /// This should be called in cases where ownership of the wrapped file
31 /// descriptor has been "moved" out of the guard.
32 ///
33 /// This is factored out into a separate function to ensure that it's
34 /// always used consistently.
35 #[inline]
36 pub fn should_not_close(&self) {
37 self.close_on_drop.store(val:false, order:Ordering::Release);
38 }
39}
40
41impl Deref for FdGuard {
42 type Target = RawFd;
43
44 #[inline]
45 fn deref(&self) -> &Self::Target {
46 &self.fd
47 }
48}
49
50impl Drop for FdGuard {
51 fn drop(&mut self) {
52 if self.close_on_drop.load(order:Ordering::Acquire) {
53 unsafe { ffi::close(self.fd); }
54 }
55 }
56}
57
58impl FromRawFd for FdGuard {
59 unsafe fn from_raw_fd(fd: RawFd) -> Self {
60 FdGuard {
61 fd,
62 close_on_drop: AtomicBool::new(true),
63 }
64 }
65}
66
67impl IntoRawFd for FdGuard {
68 fn into_raw_fd(self) -> RawFd {
69 self.should_not_close();
70 self.fd
71 }
72}
73
74impl AsRawFd for FdGuard {
75 fn as_raw_fd(&self) -> RawFd {
76 self.fd
77 }
78}
79
80impl PartialEq for FdGuard {
81 fn eq(&self, other: &FdGuard) -> bool {
82 self.fd == other.fd
83 }
84}
85