1 use std::ptr::null_mut;
2 use std::os::unix::io::RawFd;
3 use libc::{c_int, timeval};
4 use {Errno, Result};
5 use sys::time::TimeVal;
6
7 pub const FD_SETSIZE: RawFd = 1024;
8
9 #[cfg(any(target_os = "macos", target_os = "ios"))]
10 #[repr(C)]
11 #[derive(Clone)]
12 pub struct FdSet {
13 bits: [i32; FD_SETSIZE as usize / 32]
14 }
15
16 #[cfg(any(target_os = "macos", target_os = "ios"))]
17 const BITS: usize = 32;
18
19 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
20 #[repr(C)]
21 #[derive(Clone)]
22 pub struct FdSet {
23 bits: [u64; FD_SETSIZE as usize / 64]
24 }
25
26 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
27 const BITS: usize = 64;
28
29 impl FdSet {
new() -> FdSet30 pub fn new() -> FdSet {
31 FdSet {
32 bits: [0; FD_SETSIZE as usize / BITS]
33 }
34 }
35
insert(&mut self, fd: RawFd)36 pub fn insert(&mut self, fd: RawFd) {
37 let fd = fd as usize;
38 self.bits[fd / BITS] |= 1 << (fd % BITS);
39 }
40
remove(&mut self, fd: RawFd)41 pub fn remove(&mut self, fd: RawFd) {
42 let fd = fd as usize;
43 self.bits[fd / BITS] &= !(1 << (fd % BITS));
44 }
45
contains(&self, fd: RawFd) -> bool46 pub fn contains(&self, fd: RawFd) -> bool {
47 let fd = fd as usize;
48 self.bits[fd / BITS] & (1 << (fd % BITS)) > 0
49 }
50
clear(&mut self)51 pub fn clear(&mut self) {
52 for bits in &mut self.bits {
53 *bits = 0
54 }
55 }
56 }
57
58 mod ffi {
59 use libc::{c_int, timeval};
60 use super::FdSet;
61
62 extern {
select(nfds: c_int, readfds: *mut FdSet, writefds: *mut FdSet, errorfds: *mut FdSet, timeout: *mut timeval) -> c_int63 pub fn select(nfds: c_int,
64 readfds: *mut FdSet,
65 writefds: *mut FdSet,
66 errorfds: *mut FdSet,
67 timeout: *mut timeval) -> c_int;
68 }
69 }
70
select(nfds: c_int, readfds: Option<&mut FdSet>, writefds: Option<&mut FdSet>, errorfds: Option<&mut FdSet>, timeout: Option<&mut TimeVal>) -> Result<c_int>71 pub fn select(nfds: c_int,
72 readfds: Option<&mut FdSet>,
73 writefds: Option<&mut FdSet>,
74 errorfds: Option<&mut FdSet>,
75 timeout: Option<&mut TimeVal>) -> Result<c_int> {
76 let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
77 let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
78 let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
79 let timeout = timeout.map(|tv| tv as *mut TimeVal as *mut timeval)
80 .unwrap_or(null_mut());
81
82 let res = unsafe {
83 ffi::select(nfds, readfds, writefds, errorfds, timeout)
84 };
85
86 Errno::result(res)
87 }
88