2
2
use sys:: time:: TimeSpec ;
3
3
#[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "freebsd" , target_os = "dragonfly" ) ) ]
4
4
use sys:: signal:: SigSet ;
5
+ use std:: os:: unix:: io:: RawFd ;
5
6
6
7
use libc;
7
8
use { Errno , Result } ;
8
9
10
+ /// This is a wrapper around `libc::pollfd`.
11
+ ///
12
+ /// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
13
+ /// [`ppoll`](fn.ppoll.html) functions to specify the events of interested
14
+ /// for a specific file descriptor.
15
+ ///
16
+ /// After a call to `poll` or `ppoll`, the events that occured can be
17
+ /// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
9
18
#[ repr( C ) ]
10
19
#[ derive( Clone , Copy ) ]
11
20
pub struct PollFd {
12
21
pollfd : libc:: pollfd ,
13
22
}
14
23
15
24
impl PollFd {
16
- pub fn new ( fd : libc:: c_int , events : EventFlags ) -> PollFd {
25
+ /// Creates a new `PollFd` specifying the events of interested
26
+ /// for a given file descriptor.
27
+ pub fn new ( fd : RawFd , events : EventFlags ) -> PollFd {
17
28
PollFd {
18
29
pollfd : libc:: pollfd {
19
30
fd : fd,
@@ -23,26 +34,81 @@ impl PollFd {
23
34
}
24
35
}
25
36
37
+ /// Returns the events that occured in the last call to `poll` or `ppoll`.
26
38
pub fn revents ( & self ) -> Option < EventFlags > {
27
39
EventFlags :: from_bits ( self . pollfd . revents )
28
40
}
29
41
}
30
42
31
43
libc_bitflags ! {
32
44
pub flags EventFlags : libc:: c_short {
45
+ /// There is data to read.
33
46
POLLIN ,
47
+ /// There is some exceptional condition on the file descriptor.
48
+ ///
49
+ /// Possibilities include:
50
+ ///
51
+ /// * There is out-of-band data on a TCP socket (see
52
+ /// [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)).
53
+ /// * A pseudoterminal master in packet mode has seen a state
54
+ /// change on the slave (see
55
+ /// [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
56
+ /// * A cgroup.events file has been modified (see
57
+ /// [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
34
58
POLLPRI ,
59
+ /// Writing is now possible, though a write larger that the
60
+ /// available space in a socket or pipe will still block (unless
61
+ /// `O_NONBLOCK` is set).
35
62
POLLOUT ,
63
+ /// Equivalent to [`POLLIN`](constant.POLLIN.html)
36
64
POLLRDNORM ,
65
+ /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
37
66
POLLWRNORM ,
67
+ /// Priority band data can be read (generally unused on Linux).
38
68
POLLRDBAND ,
69
+ /// Priority data may be written.
39
70
POLLWRBAND ,
71
+ /// Error condition (only returned in
72
+ /// [`PollFd::revents`](struct.PollFd.html#method.revents);
73
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
74
+ /// This bit is also set for a file descriptor referring to the
75
+ /// write end of a pipe when the read end has been closed.
40
76
POLLERR ,
77
+ /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents);
78
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
79
+ /// Note that when reading from a channel such as a pipe or a stream
80
+ /// socket, this event merely indicates that the peer closed its
81
+ /// end of the channel. Subsequent reads from the channel will
82
+ /// return 0 (end of file) only after all outstanding data in the
83
+ /// channel has been consumed.
41
84
POLLHUP ,
85
+ /// Invalid request: `fd` not open (only returned in
86
+ /// [`PollFd::revents`](struct.PollFd.html#method.revents);
87
+ /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
42
88
POLLNVAL ,
43
89
}
44
90
}
45
91
92
+ /// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
93
+ /// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
94
+ ///
95
+ /// `fds` is a slice containing all [`PollFd`](struct.PollFd.html) to poll.
96
+ /// The function will return as soon as one event registered in one of the `PollFd` occurs.
97
+ ///
98
+ /// The `timeout` argument specifies the number of milliseconds that `poll()`
99
+ /// should block waiting for a file descriptor to become ready. The call
100
+ /// will block until either:
101
+ ///
102
+ /// * a file descriptor becomes ready;
103
+ /// * the call is interrupted by a signal handler; or
104
+ /// * the timeout expires.
105
+ ///
106
+ /// Note that the timeout interval will be rounded up to the system clock
107
+ /// granularity, and kernel scheduling delays mean that the blocking
108
+ /// interval may overrun by a small amount. Specifying a negative value
109
+ /// in timeout means an infinite timeout. Specifying a timeout of zero
110
+ /// causes `poll()` to return immediately, even if no file descriptors are
111
+ /// ready.
46
112
pub fn poll ( fds : & mut [ PollFd ] , timeout : libc:: c_int ) -> Result < libc:: c_int > {
47
113
let res = unsafe {
48
114
libc:: poll ( fds. as_mut_ptr ( ) as * mut libc:: pollfd ,
@@ -53,6 +119,31 @@ pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
53
119
Errno :: result ( res)
54
120
}
55
121
122
+ /// `ppoll()` allows an application to safely wait until either a file
123
+ /// descriptor becomes ready or until a signal is caught.
124
+ /// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
125
+ ///
126
+ /// The operation of `ppoll` is identical to `poll`, other than these two differences:
127
+ ///
128
+ /// * `timeout` is a `TimeSpec` which can specify time with nanosecond precision.
129
+ /// * `ppoll` changes the signal set whose delivery are blocked for the caller before polling
130
+ /// the file descriptors. This set is reverted after the polling.
131
+ /// Note that this is done **atomically**.
132
+ ///
133
+ /// It is equivalent to *atomically* executing the following calls
134
+ /// (expressed here in C):
135
+ ///
136
+ /// ```c
137
+ /// sigset_t origmask;
138
+ /// int timeout;
139
+ ///
140
+ /// timeout = (tmo_p == NULL) ? -1 :
141
+ /// (tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000);
142
+ /// pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
143
+ /// ready = poll(&fds, nfds, timeout);
144
+ /// pthread_sigmask(SIG_SETMASK, &origmask, NULL);
145
+ /// ```
146
+ ///
56
147
#[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "freebsd" , target_os = "dragonfly" ) ) ]
57
148
pub fn ppoll ( fds : & mut [ PollFd ] , timeout : TimeSpec , sigmask : SigSet ) -> Result < libc:: c_int > {
58
149
0 commit comments