@@ -2,8 +2,7 @@ use crate::errno::Errno;
2
2
use crate :: Result ;
3
3
use libc:: { self , c_int} ;
4
4
use std:: mem;
5
- use std:: os:: unix:: io:: RawFd ;
6
- use std:: ptr;
5
+ use std:: os:: unix:: io:: { FromRawFd , RawFd , OwnedFd , AsFd , AsRawFd } ;
7
6
8
7
libc_bitflags ! (
9
8
pub struct EpollFlags : c_int {
@@ -70,6 +69,107 @@ impl EpollEvent {
70
69
}
71
70
}
72
71
72
+ /// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html).
73
+ /// ```
74
+ /// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}};
75
+ /// # use nix::unistd::write;
76
+ /// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd};
77
+ /// # use std::time::{Instant, Duration};
78
+ /// # fn main() -> nix::Result<()> {
79
+ /// const DATA: u64 = 17;
80
+ /// const MILLIS: u64 = 100;
81
+ ///
82
+ /// // Create epoll
83
+ /// let epoll = Epoll::new(EpollCreateFlags::empty())?;
84
+ ///
85
+ /// // Create eventfd & Add event
86
+ /// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) };
87
+ /// epoll.add(eventfd.as_fd(), EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
88
+ ///
89
+ /// // Arm eventfd & Time wait
90
+ /// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
91
+ /// let now = Instant::now();
92
+ ///
93
+ /// // Wait on event
94
+ /// let mut events = [EpollEvent::empty()];
95
+ /// epoll.wait(&mut events, MILLIS as isize);
96
+ ///
97
+ /// // Assert data correct & timeout didn't occur
98
+ /// assert_eq!(events[0].data(), DATA);
99
+ /// assert!(now.elapsed() < Duration::from_millis(MILLIS));
100
+ /// # Ok(())
101
+ /// # }
102
+ /// ```
103
+ #[ derive( Debug ) ]
104
+ pub struct Epoll ( pub OwnedFd ) ;
105
+ impl Epoll {
106
+ /// Creates a new epoll instance and returns a file descriptor referring to that instance.
107
+ ///
108
+ /// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html).
109
+ pub fn new ( flags : EpollCreateFlags ) -> Result < Self > {
110
+ let res = unsafe { libc:: epoll_create1 ( flags. bits ( ) ) } ;
111
+ let fd = Errno :: result ( res) ?;
112
+ let owned_fd = unsafe { OwnedFd :: from_raw_fd ( fd) } ;
113
+ Ok ( Self ( owned_fd) )
114
+ }
115
+ /// Add an entry to the interest list of the epoll file descriptor for
116
+ /// specified in events.
117
+ ///
118
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`.
119
+ pub fn add < Fd : AsFd > ( & self , fd : Fd , mut event : EpollEvent ) -> Result < ( ) > {
120
+ self . epoll_ctl ( EpollOp :: EpollCtlAdd , fd. as_fd ( ) . as_raw_fd ( ) , & mut event)
121
+ }
122
+ /// Remove (deregister) the target file descriptor `fd` from the interest list.
123
+ ///
124
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` .
125
+ pub fn delete < Fd : AsFd > ( & self , fd : Fd ) -> Result < ( ) > {
126
+ self . epoll_ctl ( EpollOp :: EpollCtlDel , fd. as_fd ( ) . as_raw_fd ( ) , None )
127
+ }
128
+ /// Change the settings associated with `fd` in the interest list to the new settings specified
129
+ /// in `event`.
130
+ ///
131
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`.
132
+ pub fn modify < Fd : AsFd > ( & self , fd : Fd , event : & mut EpollEvent ) -> Result < ( ) > {
133
+ self . epoll_ctl ( EpollOp :: EpollCtlMod , fd. as_fd ( ) . as_raw_fd ( ) , event)
134
+ }
135
+ /// Waits for I/O events, blocking the calling thread if no events are currently available.
136
+ /// (This can be thought of as fetching items from the ready list of the epoll instance.)
137
+ ///
138
+ /// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
139
+ pub fn wait ( & self , events : & mut [ EpollEvent ] , timeout : isize ) -> Result < usize > {
140
+ let res = unsafe {
141
+ libc:: epoll_wait (
142
+ self . 0 . as_raw_fd ( ) ,
143
+ events. as_mut_ptr ( ) as * mut libc:: epoll_event ,
144
+ events. len ( ) as c_int ,
145
+ timeout as c_int ,
146
+ )
147
+ } ;
148
+
149
+ Errno :: result ( res) . map ( |r| r as usize )
150
+ }
151
+ /// This system call is used to add, modify, or remove entries in the interest list of the epoll
152
+ /// instance referred to by `self`. It requests that the operation `op` be performed for the
153
+ /// target file descriptor, `fd`.
154
+ ///
155
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
156
+ pub fn epoll_ctl < ' a , T > (
157
+ & self ,
158
+ op : EpollOp ,
159
+ fd : RawFd ,
160
+ event : T ,
161
+ ) -> Result < ( ) >
162
+ where
163
+ T : Into < Option < & ' a mut EpollEvent > > ,
164
+ {
165
+ let event: Option < & mut EpollEvent > = event. into ( ) ;
166
+ let ptr = event. map ( |x|& mut x. event as * mut libc:: epoll_event ) . unwrap_or ( std:: ptr:: null_mut ( ) ) ;
167
+ unsafe {
168
+ Errno :: result ( libc:: epoll_ctl ( self . 0 . as_raw_fd ( ) , op as c_int , fd, ptr) ) . map ( drop)
169
+ }
170
+ }
171
+ }
172
+
73
173
#[ inline]
74
174
pub fn epoll_create ( ) -> Result < RawFd > {
75
175
let res = unsafe { libc:: epoll_create ( 1024 ) } ;
@@ -125,4 +225,4 @@ pub fn epoll_wait(
125
225
} ;
126
226
127
227
Errno :: result ( res) . map ( |r| r as usize )
128
- }
228
+ }
0 commit comments