Code refactoring, extracting a new function wait_ms() from Curl_select and

Curl_poll() which is called whenever not a single valid file descriptor is
passed to these functions.

Improve readibility using a poll() macro to replace WSApoll().
This commit is contained in:
Yang Tse 2007-03-18 04:51:40 +00:00
parent 46a50aa001
commit 0e2d3b7b6c
2 changed files with 99 additions and 53 deletions

View File

@ -65,6 +65,33 @@
} while(0)
#endif
/*
* Internal function used for waiting a specific amount of ms
* in Curl_select() and Curl_poll() when no file descriptor is
* provided to wait on, just being used to delay execution.
* WinSock select() and poll() timeout mechanisms need a valid
* socket descriptor in a not null file descriptor set to work.
* Waiting indefinitely with this function is not allowed, a
* zero or negative timeout value will return immediately.
*/
static void wait_ms(int timeout_ms)
{
if (timeout_ms <= 0)
return;
#if defined(__MSDOS__)
delay(timeout_ms);
#elif defined(USE_WINSOCK)
Sleep(timeout_ms);
#elif defined(HAVE_POLL_FINE)
poll(NULL, 0, timeout_ms);
#else
struct timeval timeout;
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
select(0, NULL, NULL, NULL, &timeout);
#endif
}
/*
* This is an internal function used for waiting for read or write
* events on single file descriptors. It attempts to replace select()
@ -77,12 +104,26 @@
*/
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
{
#if defined(HAVE_POLL_FINE) || defined(CURL_HAVE_WSAPOLL)
#ifdef HAVE_POLL_FINE
struct pollfd pfd[2];
int num;
#else
struct timeval timeout;
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
curl_socket_t maxfd;
#endif
int r;
int ret;
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
wait_ms(timeout_ms);
return 0;
}
#ifdef HAVE_POLL_FINE
num = 0;
if (readfd != CURL_SOCKET_BAD) {
pfd[num].fd = readfd;
@ -96,11 +137,7 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
}
do {
#ifdef CURL_HAVE_WSAPOLL
r = WSAPoll(pfd, num, timeout_ms);
#else
r = poll(pfd, num, timeout_ms);
#endif
} while((r == -1) && (SOCKERRNO == EINTR));
if (r < 0)
@ -132,33 +169,12 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
}
return ret;
#else
struct timeval timeout;
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
curl_socket_t maxfd;
int r;
int ret;
#else /* HAVE_POLL_FINE */
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
/* According to POSIX we should pass in NULL pointers if we don't want to
wait for anything in particular but just use the timeout function.
Windows however returns immediately if done so. I copied the MSDOS
delay() use from src/main.c that already had this work-around. */
#ifdef WIN32
Sleep(timeout_ms);
#elif defined(__MSDOS__)
delay(timeout_ms);
#else
select(0, NULL, NULL, NULL, &timeout);
#endif
return 0;
}
FD_ZERO(&fds_err);
maxfd = (curl_socket_t)-1;
@ -203,7 +219,9 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
}
return ret;
#endif
#endif /* HAVE_POLL_FINE */
}
/*
@ -218,23 +236,38 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
*/
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
{
int r;
#ifdef HAVE_POLL_FINE
do {
#ifdef CURL_HAVE_WSAPOLL
r = WSAPoll(ufds, nfds, timeout_ms);
#else
r = poll(ufds, nfds, timeout_ms);
#endif
} while((r == -1) && (SOCKERRNO == EINTR));
#else /* HAVE_POLL_FINE */
#ifndef HAVE_POLL_FINE
struct timeval timeout;
struct timeval *ptimeout;
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
curl_socket_t maxfd;
#endif
bool fds_none = TRUE;
unsigned int i;
int r;
if (ufds) {
for (i = 0; i < nfds; i++) {
if (ufds[i].fd != CURL_SOCKET_BAD) {
fds_none = FALSE;
break;
}
}
}
if (fds_none) {
wait_ms(timeout_ms);
return 0;
}
#ifdef HAVE_POLL_FINE
do {
r = poll(ufds, nfds, timeout_ms);
} while((r == -1) && (SOCKERRNO == EINTR));
#else /* HAVE_POLL_FINE */
FD_ZERO(&fds_read);
FD_ZERO(&fds_write);
@ -244,13 +277,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
for (i = 0; i < nfds; i++) {
if (ufds[i].fd == CURL_SOCKET_BAD)
continue;
#if !defined(USE_WINSOCK) && !defined(TPF)
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
if (ufds[i].fd >= FD_SETSIZE) {
SET_SOCKERRNO(EINVAL);
return -1;
}
#endif
VERIFY_SOCK(ufds[i].fd);
if (ufds[i].fd > maxfd)
maxfd = ufds[i].fd;
if (ufds[i].events & POLLIN)
@ -292,7 +319,9 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
if (ufds[i].revents != 0)
r++;
}
#endif /* HAVE_POLL_FINE */
return r;
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -23,13 +23,30 @@
* $Id$
***************************************************************************/
#include "setup.h"
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
/* for Vista, use WSAPoll(). */
#include <winsock2.h>
#define CURL_HAVE_WSAPOLL
#else
#endif
/*
* poll() function on Windows Vista and later is called WSAPoll()
*/
#if defined(USE_WINSOCK) && (USE_WINSOCK > 1) && \
defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
#undef HAVE_POLL
#define HAVE_POLL 1
#undef HAVE_POLL_FINE
#define HAVE_POLL_FINE 1
#define poll(x,y,z) WSAPoll((x),(y),(z))
#endif
/*
* Definition of pollfd struct and constants for platforms lacking them.
*/
#ifndef HAVE_POLL
#define POLLIN 0x01
#define POLLPRI 0x02
@ -60,4 +77,4 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval* tv);
#endif
#endif
#endif /* __SELECT_H */