/*-------------------------------------------------------------------------
 *
 * select.c
 *	  Microsoft Windows Win32 select() replacement that handles
 *		  postgresqls local signal handling.
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include "libpq/pqsignal.h"

int
pqselect(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *timeout)
{
	int			secondsleft;
	struct timeval timeoutstep;
	int			res;

	if (!timeout)
		return select(n, r, w, e, timeout);

	secondsleft = timeout->tv_sec;

	while (secondsleft > 0)
	{
		fd_set		ri,
					wi,
					ei;

		memset(&timeoutstep, 0, sizeof(timeoutstep));
		timeoutstep.tv_sec = 1;
		secondsleft--;

		if (r)
			memcpy(&ri, r, sizeof(fd_set));
		if (w)
			memcpy(&wi, w, sizeof(fd_set));
		if (e)
			memcpy(&ei, e, sizeof(fd_set));

		res = select(n, r ? &ri : NULL, (w != NULL) ? &wi : NULL, (e != NULL) ? &ei : NULL, &timeoutstep);
		if (res != 0)
		{
			if (r)
				memcpy(r, &ri, sizeof(fd_set));
			if (w)
				memcpy(w, &wi, sizeof(fd_set));
			if (e)
				memcpy(e, &ei, sizeof(fd_set));
			return res;			/* Everything except timeout */
		}

		PG_POLL_SIGNALS();
	}

	if (timeout->tv_usec)
	{
		/* Subsecond timeout left */
		timeoutstep.tv_sec = 0;
		timeoutstep.tv_usec = timeout->tv_usec;
		return select(n, r, w, e, &timeoutstep);
	}
	if (r)
		FD_ZERO(r);
	if (w)
		FD_ZERO(w);
	if (e)
		FD_ZERO(e);
	return 0;					/* If all select():s timed out */
}
