/*****************************************************************************
* poll.c: I/O event multiplexing
*****************************************************************************
- * Copyright © 2007 Rémi Denis-Courmont
+ * Copyright © 2007-2008 Rémi Denis-Courmont
* $Id$
*
* Author: Rémi Denis-Courmont
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
-#ifndef HAVE_POLL
+#include <vlc_common.h>
+#include <vlc_network.h>
+
+#ifndef WIN32
+struct pollfd;
+
+int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
+{
+ (void)fds; (void)nfds; (void)timeout;
+ abort ();
+}
+#else
#include <string.h>
#include <stdlib.h>
#include <vlc_network.h>
-int poll (struct pollfd *fds, unsigned nfds, int timeout)
+int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
{
- fd_set rdset, wrset, exset;
- struct timeval tv = { 0, 0 };
- int val = -1;
+ WSAEVENT phEvents[nfds];
+ DWORD val;
+ vlc_testcancel ();
- FD_ZERO (&rdset);
- FD_ZERO (&wrset);
- FD_ZERO (&exset);
for (unsigned i = 0; i < nfds; i++)
{
- int fd = fds[i].fd;
- if (val < fd)
- val = fd;
+ long events = FD_CLOSE;
- /* I assume the OS has a solution select overflow if it does not have
- * poll(). If it did not, we are screwed anyway. */
if (fds[i].events & POLLIN)
- FD_SET (fd, &rdset);
+ events |= FD_READ | FD_ACCEPT;
if (fds[i].events & POLLOUT)
- FD_SET (fd, &wrset);
+ events |= FD_WRITE;
if (fds[i].events & POLLPRI)
- FD_SET (fd, &exset);
- }
+ events |= FD_OOB;
+ fds[i].revents = 0;
- if (timeout >= 0)
- {
- div_t d = div (timeout, 1000);
- tv.tv_sec = d.quot;
- tv.tv_usec = d.rem * 1000;
+ phEvents[i] = WSACreateEvent ();
+ WSAEventSelect (fds[i].fd, phEvents[i], events);
}
- val = select (val + 1, &rdset, &wrset, NULL,
- (timeout >= 0) ? &tv : NULL);
- if (val == -1)
- return -1;
+ int ret = 0, n = 0;
- for (unsigned i = 0; i < nfds; i++)
+ switch (WaitForMultipleObjectsEx (nfds, phEvents, FALSE, timeout, TRUE))
{
- int fd = fds[i].fd;
- fds[i].revents = (FD_ISSET (fds[i].fd, &rdset) ? POLLIN : 0)
- | (FD_ISSET (fds[i].fd, &wrset) ? POLLOUT : 0)
- | (FD_ISSET (fds[i].fd, &exset) ? POLLPRI : 0);
+ case WAIT_IO_COMPLETION:
+ WSASetLastError (WSAEINTR);
+ ret = -1;
+ break;
+ case WAIT_TIMEOUT:
+ ret = 0;
+ break;
+ default:
+ for (unsigned i = 0; i < nfds; i++)
+ {
+ WSANETWORKEVENTS events;
+ if (WSAEnumNetworkEvents (fds[i].fd, phEvents[i], &events))
+ {
+ fds[i].revents |= POLLNVAL;
+ ret = -1;
+ continue;
+ }
+ if (events.lNetworkEvents & FD_CLOSE)
+ fds[i].revents |= POLLHUP | (fds[i].events & POLLIN);
+ if (events.lNetworkEvents & FD_ACCEPT)
+ fds[i].revents |= POLLIN;
+ if (events.lNetworkEvents & FD_OOB)
+ fds[i].revents |= POLLPRI;
+ if (events.lNetworkEvents & FD_READ)
+ fds[i].revents |= POLLIN;
+ if (events.lNetworkEvents & FD_WRITE)
+ {
+ fds[i].revents |= POLLOUT;
+ if (events.iErrorCode[FD_WRITE_BIT])
+ fds[i].revents |= POLLERR;
+ }
+ if (fds[i].events)
+ n++;
+ }
+ if (ret == 0)
+ ret = n;
}
- return val;
+
+ for (unsigned i = 0; i < nfds; i++)
+ WSACloseEvent (phEvents[i]);
+ vlc_testcancel ();
+
+ return ret;
}
-#endif /* !HAVE_POLL */
+#endif /* WIN32 */