diff options
Diffstat (limited to 'src/sys/select.rs')
-rw-r--r-- | src/sys/select.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/sys/select.rs b/src/sys/select.rs new file mode 100644 index 00000000..1060d618 --- /dev/null +++ b/src/sys/select.rs @@ -0,0 +1,84 @@ +use std::ptr::null_mut; +use std::os::unix::io::RawFd; +use libc::c_int; +use {Result, Error}; +use errno::Errno; +use sys::time::TimeVal; + +pub const FD_SETSIZE: RawFd = 1024; + +#[cfg(any(target_os = "macos", target_os = "ios"))] +#[repr(C)] +pub struct FdSet { + bits: [i32; FD_SETSIZE as usize / 32] +} + +#[cfg(any(target_os = "macos", target_os = "ios"))] +const BITS: usize = 32; + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +#[repr(C)] +pub struct FdSet { + bits: [u64; FD_SETSIZE as usize / 64] +} + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +const BITS: usize = 64; + +impl FdSet { + pub fn new() -> FdSet { + FdSet { + bits: [0; FD_SETSIZE as usize / BITS] + } + } + + pub fn insert(&mut self, fd: RawFd) { + let fd = fd as usize; + self.bits[fd / BITS] |= 1 << (fd % BITS); + } + + pub fn remove(&mut self, fd: RawFd) { + let fd = fd as usize; + self.bits[fd / BITS] &= !(1 << (fd % BITS)); + } + + pub fn contains(&mut self, fd: RawFd) -> bool { + let fd = fd as usize; + self.bits[fd / BITS] & (1 << (fd % BITS)) > 0 + } +} + +mod ffi { + use libc::c_int; + use sys::time::TimeVal; + use super::FdSet; + + extern { + pub fn select(nfds: c_int, + readfds: *mut FdSet, + writefds: *mut FdSet, + errorfds: *mut FdSet, + timeout: *mut TimeVal) -> c_int; + } +} + +pub fn select(nfds: c_int, + readfds: Option<&mut FdSet>, + writefds: Option<&mut FdSet>, + errorfds: Option<&mut FdSet>, + timeout: &mut TimeVal) -> Result<c_int> { + let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let timeout = timeout as *mut TimeVal; + + let res = unsafe { + ffi::select(nfds, readfds, writefds, errorfds, timeout) + }; + + if res == -1 { + Err(Error::Sys(Errno::last())) + } else { + Ok(res) + } +} |