internal void PollFds(List<libc.pollfd> readyFds) { int count; libc.pollfd[] pollFds; readyFds.Clear(); lock (this) { // TODO: Avoid the allocation when count is in 100s count = _fdSet.Count + 1; pollFds = new libc.pollfd[count]; // Always include special fd in the poll set. This is used to // return from the poll in case any fds have been added or // removed to the set of fds being polled. This prevents starvation // in case current set of fds have no activity but the new fd // is ready for a read/write. The special fd is the read end of a pipe // Whenever an fd is added/removed in _fdSet, a write happens to the // write end of the pipe thus causing the poll to return. pollFds[0].fd = _specialFds[libc.ReadEndOfPipe]; pollFds[0].events = PollFlags.POLLIN | PollFlags.POLLOUT; int i = 1; foreach (int fd in _fdSet) { pollFds[i].fd = fd; pollFds[i].events = PollFlags.POLLIN | PollFlags.POLLOUT; i++; } } unsafe { fixed (libc.pollfd* fds = pollFds) { int numFds = libc.poll(fds, (uint)count, -1); if (numFds <= 0) { Debug.Assert(numFds != 0); // Since timeout is infinite // TODO: How to handle errors? throw new InvalidOperationException("Poll failure: " + Marshal.GetLastWin32Error()); } lock (this) { if (0 == _requestCount) { return; } } // Check for any fdset changes if (fds[0].revents != 0) { if (ReadSpecialFd(fds[0].revents) < 0) { // TODO: How to handle errors? throw new InvalidOperationException("Cannot read data: " + Marshal.GetLastWin32Error()); } numFds--; } // Now check for events on the remaining fds for (int i = 1; i < count && numFds > 0; i++) { if (fds[i].revents == 0) { continue; } readyFds.Add(fds[i]); numFds--; } } } }
internal void PollFds(List <libc.pollfd> readyFds) { int count; libc.pollfd[] pollFds; readyFds.Clear(); lock (this) { // TODO: Avoid the allocation when count is in 100s count = _fdSet.Count + 1; pollFds = new libc.pollfd[count]; // Always include special fd in the poll set. This is used to // return from the poll in case any fds have been added or // removed to the set of fds being polled. This prevents starvation // in case current set of fds have no activity but the new fd // is ready for a read/write. The special fd is the read end of a pipe // Whenever an fd is added/removed in _fdSet, a write happens to the // write end of the pipe thus causing the poll to return. pollFds[0].fd = _specialFds[Interop.Sys.ReadEndOfPipe]; pollFds[0].events = PollFlags.POLLIN; int i = 1; foreach (int fd in _fdSet) { pollFds[i].fd = fd; pollFds[i].events = PollFlags.POLLIN | PollFlags.POLLOUT; i++; } } unsafe { fixed(libc.pollfd *fds = pollFds) { int numFds = libc.poll(fds, (uint)count, -1); if (numFds <= 0) { Debug.Assert(numFds != 0); // Since timeout is infinite // TODO: How to handle errors? throw new InvalidOperationException("Poll failure: " + Marshal.GetLastWin32Error()); } lock (this) { if (0 == _requestCount) { return; } } // Check for any fdset changes if (fds[0].revents != 0) { if (ReadSpecialFd(fds[0].revents) < 0) { // TODO: How to handle errors? throw new InvalidOperationException("Cannot read data: " + Marshal.GetLastWin32Error()); } numFds--; } // Now check for events on the remaining fds for (int i = 1; i < count && numFds > 0; i++) { if (fds[i].revents == 0) { continue; } readyFds.Add(fds[i]); numFds--; } } } }