@@ -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 {
@@ -26,6 +25,107 @@ libc_bitflags!(
26
25
}
27
26
) ;
28
27
28
+ /// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html).
29
+ /// ```
30
+ /// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}};
31
+ /// # use nix::unistd::write;
32
+ /// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd};
33
+ /// # use std::time::{Instant, Duration};
34
+ /// # fn main() -> nix::Result<()> {
35
+ /// const DATA: u64 = 17;
36
+ /// const MILLIS: u64 = 100;
37
+ ///
38
+ /// // Create epoll
39
+ /// let epoll = Epoll::new(EpollCreateFlags::empty())?;
40
+ ///
41
+ /// // Create eventfd & Add event
42
+ /// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) };
43
+ /// epoll.add(eventfd.as_fd(), EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
44
+ ///
45
+ /// // Arm eventfd & Time wait
46
+ /// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
47
+ /// let now = Instant::now();
48
+ ///
49
+ /// // Wait on event
50
+ /// let mut events = [EpollEvent::empty()];
51
+ /// epoll.wait(&mut events, MILLIS as isize);
52
+ ///
53
+ /// // Assert data correct & timeout didn't occur
54
+ /// assert_eq!(events[0].data(), DATA);
55
+ /// assert!(now.elapsed() < Duration::from_millis(MILLIS));
56
+ /// # Ok(())
57
+ /// # }
58
+ /// ```
59
+ #[ derive( Debug ) ]
60
+ pub struct Epoll ( pub OwnedFd ) ;
61
+ impl Epoll {
62
+ /// Creates a new epoll instance and returns a file descriptor referring to that instance.
63
+ ///
64
+ /// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html).
65
+ pub fn new ( flags : EpollCreateFlags ) -> Result < Self > {
66
+ let res = unsafe { libc:: epoll_create1 ( flags. bits ( ) ) } ;
67
+ let fd = Errno :: result ( res) ?;
68
+ let owned_fd = unsafe { OwnedFd :: from_raw_fd ( fd) } ;
69
+ Ok ( Self ( owned_fd) )
70
+ }
71
+ /// Add an entry to the interest list of the epoll file descriptor for
72
+ /// specified in events.
73
+ ///
74
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`.
75
+ pub fn add < Fd : AsFd > ( & self , fd : Fd , mut event : EpollEvent ) -> Result < ( ) > {
76
+ self . epoll_ctl ( EpollOp :: EpollCtlAdd , fd. as_fd ( ) . as_raw_fd ( ) , & mut event)
77
+ }
78
+ /// Remove (deregister) the target file descriptor `fd` from the interest list.
79
+ ///
80
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` .
81
+ pub fn delete < Fd : AsFd > ( & self , fd : Fd ) -> Result < ( ) > {
82
+ self . epoll_ctl ( EpollOp :: EpollCtlDel , fd. as_fd ( ) . as_raw_fd ( ) , None )
83
+ }
84
+ /// Change the settings associated with `fd` in the interest list to the new settings specified
85
+ /// in `event`.
86
+ ///
87
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`.
88
+ pub fn modify < Fd : AsFd > ( & self , fd : Fd , event : & mut EpollEvent ) -> Result < ( ) > {
89
+ self . epoll_ctl ( EpollOp :: EpollCtlMod , fd. as_fd ( ) . as_raw_fd ( ) , event)
90
+ }
91
+ /// Waits for I/O events, blocking the calling thread if no events are currently available.
92
+ /// (This can be thought of as fetching items from the ready list of the epoll instance.)
93
+ ///
94
+ /// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
95
+ pub fn wait ( & self , events : & mut [ EpollEvent ] , timeout : isize ) -> Result < usize > {
96
+ let res = unsafe {
97
+ libc:: epoll_wait (
98
+ self . 0 . as_raw_fd ( ) ,
99
+ events. as_mut_ptr ( ) as * mut libc:: epoll_event ,
100
+ events. len ( ) as c_int ,
101
+ timeout as c_int ,
102
+ )
103
+ } ;
104
+
105
+ Errno :: result ( res) . map ( |r| r as usize )
106
+ }
107
+ /// This system call is used to add, modify, or remove entries in the interest list of the epoll
108
+ /// instance referred to by `self`. It requests that the operation `op` be performed for the
109
+ /// target file descriptor, `fd`.
110
+ ///
111
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
112
+ pub fn epoll_ctl < ' a , T > (
113
+ & self ,
114
+ op : EpollOp ,
115
+ fd : RawFd ,
116
+ event : T ,
117
+ ) -> Result < ( ) >
118
+ where
119
+ T : Into < Option < & ' a mut EpollEvent > > ,
120
+ {
121
+ let event: Option < & mut EpollEvent > = event. into ( ) ;
122
+ let ptr = event. map ( |x|& mut x. event as * mut libc:: epoll_event ) . unwrap_or ( std:: ptr:: null_mut ( ) ) ;
123
+ unsafe {
124
+ Errno :: result ( libc:: epoll_ctl ( self . 0 . as_raw_fd ( ) , op as c_int , fd, ptr) ) . map ( drop)
125
+ }
126
+ }
127
+ }
128
+
29
129
#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
30
130
#[ repr( i32 ) ]
31
131
#[ non_exhaustive]
@@ -68,61 +168,4 @@ impl EpollEvent {
68
168
pub fn data ( & self ) -> u64 {
69
169
self . event . u64
70
170
}
71
- }
72
-
73
- #[ inline]
74
- pub fn epoll_create ( ) -> Result < RawFd > {
75
- let res = unsafe { libc:: epoll_create ( 1024 ) } ;
76
-
77
- Errno :: result ( res)
78
- }
79
-
80
- #[ inline]
81
- pub fn epoll_create1 ( flags : EpollCreateFlags ) -> Result < RawFd > {
82
- let res = unsafe { libc:: epoll_create1 ( flags. bits ( ) ) } ;
83
-
84
- Errno :: result ( res)
85
- }
86
-
87
- #[ inline]
88
- pub fn epoll_ctl < ' a , T > (
89
- epfd : RawFd ,
90
- op : EpollOp ,
91
- fd : RawFd ,
92
- event : T ,
93
- ) -> Result < ( ) >
94
- where
95
- T : Into < Option < & ' a mut EpollEvent > > ,
96
- {
97
- let mut event: Option < & mut EpollEvent > = event. into ( ) ;
98
- if event. is_none ( ) && op != EpollOp :: EpollCtlDel {
99
- Err ( Errno :: EINVAL )
100
- } else {
101
- let res = unsafe {
102
- if let Some ( ref mut event) = event {
103
- libc:: epoll_ctl ( epfd, op as c_int , fd, & mut event. event )
104
- } else {
105
- libc:: epoll_ctl ( epfd, op as c_int , fd, ptr:: null_mut ( ) )
106
- }
107
- } ;
108
- Errno :: result ( res) . map ( drop)
109
- }
110
- }
111
-
112
- #[ inline]
113
- pub fn epoll_wait (
114
- epfd : RawFd ,
115
- events : & mut [ EpollEvent ] ,
116
- timeout_ms : isize ,
117
- ) -> Result < usize > {
118
- let res = unsafe {
119
- libc:: epoll_wait (
120
- epfd,
121
- events. as_mut_ptr ( ) as * mut libc:: epoll_event ,
122
- events. len ( ) as c_int ,
123
- timeout_ms as c_int ,
124
- )
125
- } ;
126
-
127
- Errno :: result ( res) . map ( |r| r as usize )
128
- }
171
+ }
0 commit comments