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