-
Notifications
You must be signed in to change notification settings - Fork 696
Add select::FdSet::fds() method #1207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1b5ea70
41db1bf
8b4a433
4a101ae
bcfcf82
eb5f289
1171817
e8c7961
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
use std::iter::FusedIterator; | ||
use std::mem; | ||
use std::ops::Range; | ||
use std::os::unix::io::RawFd; | ||
use std::ptr::{null, null_mut}; | ||
use libc::{self, c_int}; | ||
|
@@ -30,8 +32,9 @@ impl FdSet { | |
unsafe { libc::FD_CLR(fd, &mut self.0) }; | ||
} | ||
|
||
pub fn contains(&mut self, fd: RawFd) -> bool { | ||
unsafe { libc::FD_ISSET(fd, &mut self.0) } | ||
pub fn contains(&self, fd: RawFd) -> bool { | ||
let mut copy = self.0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As an aside, if we're worried about the cost of this copy, then we might want to consider not deriving There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You know, that's an excellent point. On my system, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that for now we should proceed without waiting for rust-lang/libc#1725 . But copying the entire structure on each loop of the iterator is woefully inefficient. I think you should retain the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. This sadly means that the iterator cannot implement |
||
unsafe { libc::FD_ISSET(fd, &mut copy) } | ||
} | ||
|
||
pub fn clear(&mut self) { | ||
|
@@ -58,15 +61,32 @@ impl FdSet { | |
/// ``` | ||
/// | ||
/// [`select`]: fn.select.html | ||
pub fn highest(&mut self) -> Option<RawFd> { | ||
for i in (0..FD_SETSIZE).rev() { | ||
let i = i as RawFd; | ||
if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } { | ||
return Some(i) | ||
} | ||
} | ||
pub fn highest(&self) -> Option<RawFd> { | ||
self.fds().next_back() | ||
} | ||
|
||
None | ||
/// Returns an iterator over the file descriptors in the set. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// # extern crate nix; | ||
/// # use nix::sys::select::FdSet; | ||
/// # use std::os::unix::io::RawFd; | ||
/// # fn main() { | ||
zombiezen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// let mut set = FdSet::new(); | ||
/// set.insert(4); | ||
/// set.insert(9); | ||
/// let fds: Vec<RawFd> = set.fds().collect(); | ||
/// assert_eq!(fds, vec![4, 9]); | ||
/// # } | ||
/// ``` | ||
#[inline] | ||
pub fn fds(&self) -> Fds { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically a C programmer will know what the maximum file descriptor he registered was, and when inspecting the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added to |
||
Fds { | ||
set: self, | ||
range: 0..FD_SETSIZE, | ||
} | ||
} | ||
} | ||
|
||
|
@@ -76,6 +96,46 @@ impl Default for FdSet { | |
} | ||
} | ||
|
||
/// Iterator over `FdSet`. | ||
#[derive(Clone, Debug)] | ||
pub struct Fds<'a> { | ||
set: &'a FdSet, | ||
range: Range<usize>, | ||
} | ||
|
||
impl<'a> Iterator for Fds<'a> { | ||
type Item = RawFd; | ||
|
||
fn next(&mut self) -> Option<RawFd> { | ||
while let Some(i) = self.range.next() { | ||
if self.set.contains(i as RawFd) { | ||
return Some(i as RawFd); | ||
} | ||
} | ||
None | ||
} | ||
|
||
#[inline] | ||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
let (_, upper) = self.range.size_hint(); | ||
(0, upper) | ||
} | ||
} | ||
|
||
impl<'a> DoubleEndedIterator for Fds<'a> { | ||
#[inline] | ||
fn next_back(&mut self) -> Option<RawFd> { | ||
while let Some(i) = self.range.next_back() { | ||
if self.set.contains(i as RawFd) { | ||
return Some(i as RawFd); | ||
} | ||
} | ||
None | ||
} | ||
} | ||
|
||
impl<'a> FusedIterator for Fds<'a> {} | ||
|
||
/// Monitors file descriptors for readiness | ||
/// | ||
/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all | ||
|
@@ -100,9 +160,9 @@ impl Default for FdSet { | |
/// | ||
/// [`FdSet::highest`]: struct.FdSet.html#method.highest | ||
pub fn select<'a, N, R, W, E, T>(nfds: N, | ||
readfds: R, | ||
writefds: W, | ||
errorfds: E, | ||
readfds: R, | ||
writefds: W, | ||
errorfds: E, | ||
timeout: T) -> Result<c_int> | ||
where | ||
N: Into<Option<c_int>>, | ||
|
@@ -129,7 +189,7 @@ where | |
let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); | ||
let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); | ||
let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval) | ||
.unwrap_or(null_mut()); | ||
.unwrap_or(null_mut()); | ||
|
||
let res = unsafe { | ||
libc::select(nfds, readfds, writefds, errorfds, timeout) | ||
|
@@ -168,10 +228,10 @@ where | |
/// | ||
/// [`FdSet::highest`]: struct.FdSet.html#method.highest | ||
pub fn pselect<'a, N, R, W, E, T, S>(nfds: N, | ||
readfds: R, | ||
writefds: W, | ||
errorfds: E, | ||
timeout: T, | ||
readfds: R, | ||
writefds: W, | ||
errorfds: E, | ||
timeout: T, | ||
sigmask: S) -> Result<c_int> | ||
where | ||
N: Into<Option<c_int>>, | ||
|
@@ -311,9 +371,9 @@ mod tests { | |
|
||
let mut timeout = TimeVal::seconds(10); | ||
assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1), | ||
&mut fd_set, | ||
None, | ||
None, | ||
&mut fd_set, | ||
None, | ||
None, | ||
&mut timeout).unwrap()); | ||
assert!(fd_set.contains(r1)); | ||
assert!(!fd_set.contains(r2)); | ||
|
@@ -331,9 +391,9 @@ mod tests { | |
|
||
let mut timeout = TimeVal::seconds(10); | ||
assert_eq!(1, select(::std::cmp::max(r1, r2) + 1, | ||
&mut fd_set, | ||
None, | ||
None, | ||
&mut fd_set, | ||
None, | ||
None, | ||
&mut timeout).unwrap()); | ||
assert!(fd_set.contains(r1)); | ||
assert!(!fd_set.contains(r2)); | ||
|
Uh oh!
There was an error while loading. Please reload this page.