borrowed emulated poll for win32 from gnulib
This commit is contained in:
		| @ -47,6 +47,14 @@ | |||||||
| #		include <ltdl.h> | #		include <ltdl.h> | ||||||
| #		define USE_LTDL | #		define USE_LTDL | ||||||
| #	endif | #	endif | ||||||
|  |  | ||||||
|  | #	include "poll-msw.h" | ||||||
|  | #	define USE_POLL | ||||||
|  | #	define XPOLLIN POLLIN | ||||||
|  | #	define XPOLLOUT POLLOUT | ||||||
|  | #	define XPOLLERR POLLERR | ||||||
|  | #	define XPOLLHUP POLLHUP | ||||||
|  |  | ||||||
| #elif defined(__OS2__) | #elif defined(__OS2__) | ||||||
| #	define INCL_DOSMODULEMGR | #	define INCL_DOSMODULEMGR | ||||||
| #	define INCL_DOSPROCESS | #	define INCL_DOSPROCESS | ||||||
| @ -238,7 +246,7 @@ struct xtn_t | |||||||
|  |  | ||||||
| 	#if defined(_WIN32) | 	#if defined(_WIN32) | ||||||
| 	HANDLE waitable_timer; | 	HANDLE waitable_timer; | ||||||
| #else | 	#endif | ||||||
|  |  | ||||||
| 	#if defined(USE_DEVPOLL) | 	#if defined(USE_DEVPOLL) | ||||||
| 	int ep; /* /dev/poll */ | 	int ep; /* /dev/poll */ | ||||||
| @ -301,7 +309,6 @@ struct xtn_t | |||||||
| 		pthread_cond_t cnd2; | 		pthread_cond_t cnd2; | ||||||
| 	#endif | 	#endif | ||||||
| 	} ev; | 	} ev; | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
| @ -563,15 +570,6 @@ static void free_heap (moo_t* moo, void* ptr) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(_WIN32) |  | ||||||
| 	/* nothing to do */ |  | ||||||
|  |  | ||||||
| #elif defined(macintosh) |  | ||||||
| 	/* nothing to do */ |  | ||||||
|  |  | ||||||
| #else |  | ||||||
|  |  | ||||||
| static int write_all (int fd, const moo_bch_t* ptr, moo_oow_t len) | static int write_all (int fd, const moo_bch_t* ptr, moo_oow_t len) | ||||||
| { | { | ||||||
| 	while (len > 0) | 	while (len > 0) | ||||||
| @ -605,7 +603,6 @@ static int write_all (int fd, const moo_bch_t* ptr, moo_oow_t len) | |||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static int write_log (moo_t* moo, int fd, const moo_bch_t* ptr, moo_oow_t len) | static int write_log (moo_t* moo, int fd, const moo_bch_t* ptr, moo_oow_t len) | ||||||
| { | { | ||||||
| @ -2121,7 +2118,7 @@ static void setup_tick (void) | |||||||
| 	g_tick_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); | 	g_tick_timer = CreateWaitableTimer(MOO_NULL, TRUE, MOO_NULL); | ||||||
| 	if (g_tick_timer) | 	if (g_tick_timer) | ||||||
| 	{ | 	{ | ||||||
| 		li.QuadPart = -li.QuadPart = -MOO_SECNSEC_TO_NSEC(0, 20000); /* 20000 microseconds. 0.02 seconds */ | 		li.QuadPart = -MOO_SECNSEC_TO_NSEC(0, 20000); /* 20000 microseconds. 0.02 seconds */ | ||||||
| 		SetWaitableTimer (g_tick_timer, &li, 0, arrange_process_switching, MOO_NULL, FALSE); | 		SetWaitableTimer (g_tick_timer, &li, 0, arrange_process_switching, MOO_NULL, FALSE); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										412
									
								
								moo/lib/poll-msw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								moo/lib/poll-msw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,412 @@ | |||||||
|  | /* Emulation for poll(2) | ||||||
|  |    Contributed by Paolo Bonzini. | ||||||
|  |  | ||||||
|  |    Copyright 2001-2003, 2006-2016 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  |    This file is part of gnulib. | ||||||
|  |  | ||||||
|  |    This program is free software; you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU General Public License as published by | ||||||
|  |    the Free Software Foundation; either version 2, or (at your option) | ||||||
|  |    any later version. | ||||||
|  |  | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |    You should have received a copy of the GNU General Public License along | ||||||
|  |    with this program; if not, see <http://www.gnu.org/licenses/>.  */ | ||||||
|  |  | ||||||
|  | /* Tell gcc not to warn about the (nfd < 0) tests, below.  */ | ||||||
|  | #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ | ||||||
|  | # pragma GCC diagnostic ignored "-Wtype-limits" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include "poll-msw.h" | ||||||
|  | #include <winsock2.h> | ||||||
|  | #include <windows.h> | ||||||
|  |  | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <limits.h> | ||||||
|  |  | ||||||
|  | #ifndef INFTIM | ||||||
|  | #	define INFTIM (-1) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* BeOS does not have MSG_PEEK.  */ | ||||||
|  | #ifndef MSG_PEEK | ||||||
|  | #	define MSG_PEEK 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef POLLRDNORM | ||||||
|  | #	define POLLRDNORM  0 | ||||||
|  | #	define POLLRDBAND  0 | ||||||
|  | #	define POLLWRNORM  0 | ||||||
|  | #	define POLLWRBAND  0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static BOOL IsConsoleHandle (HANDLE h) | ||||||
|  | { | ||||||
|  | 	DWORD mode; | ||||||
|  | 	return GetConsoleMode (h, &mode) != 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static BOOL IsSocketHandle (HANDLE h) | ||||||
|  | { | ||||||
|  | 	WSANETWORKEVENTS ev; | ||||||
|  |  | ||||||
|  | 	if (IsConsoleHandle (h)) return FALSE; | ||||||
|  |  | ||||||
|  | 	/* Under Wine, it seems that getsockopt returns 0 for pipes too. | ||||||
|  | 	   WSAEnumNetworkEvents instead distinguishes the two correctly.  */ | ||||||
|  | 	ev.lNetworkEvents = 0xDEADBEEF; | ||||||
|  | 	WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); | ||||||
|  | 	return ev.lNetworkEvents != 0xDEADBEEF; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Declare data structures for ntdll functions.  */ | ||||||
|  | typedef struct _FILE_PIPE_LOCAL_INFORMATION | ||||||
|  | { | ||||||
|  | 	ULONG NamedPipeType; | ||||||
|  | 	ULONG NamedPipeConfiguration; | ||||||
|  | 	ULONG MaximumInstances; | ||||||
|  | 	ULONG CurrentInstances; | ||||||
|  | 	ULONG InboundQuota; | ||||||
|  | 	ULONG ReadDataAvailable; | ||||||
|  | 	ULONG OutboundQuota; | ||||||
|  | 	ULONG WriteQuotaAvailable; | ||||||
|  | 	ULONG NamedPipeState; | ||||||
|  | 	ULONG NamedPipeEnd; | ||||||
|  | } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; | ||||||
|  |  | ||||||
|  | typedef struct _IO_STATUS_BLOCK | ||||||
|  | { | ||||||
|  | 	union | ||||||
|  | 	{ | ||||||
|  | 		DWORD Status; | ||||||
|  | 		PVOID Pointer; | ||||||
|  | 	} u; | ||||||
|  | 	ULONG_PTR Information; | ||||||
|  | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; | ||||||
|  |  | ||||||
|  | typedef enum _FILE_INFORMATION_CLASS | ||||||
|  | { | ||||||
|  |     FilePipeLocalInformation = 24 | ||||||
|  | } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; | ||||||
|  |  | ||||||
|  | typedef DWORD (WINAPI *PNtQueryInformationFile) (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS); | ||||||
|  |  | ||||||
|  | # ifndef PIPE_BUF | ||||||
|  | #  define PIPE_BUF      512 | ||||||
|  | # endif | ||||||
|  |  | ||||||
|  | /* Compute revents values for file handle H.  If some events cannot happen | ||||||
|  |    for the handle, eliminate them from *P_SOUGHT.  */ | ||||||
|  |  | ||||||
|  | static int windows_compute_revents (HANDLE h, int *p_sought) | ||||||
|  | { | ||||||
|  | 	int i, ret, happened; | ||||||
|  | 	INPUT_RECORD *irbuffer; | ||||||
|  | 	DWORD avail, nbuffer; | ||||||
|  | 	BOOL bRet; | ||||||
|  | 	IO_STATUS_BLOCK iosb; | ||||||
|  | 	FILE_PIPE_LOCAL_INFORMATION fpli; | ||||||
|  | 	static PNtQueryInformationFile NtQueryInformationFile; | ||||||
|  | 	static BOOL once_only; | ||||||
|  |  | ||||||
|  | 	switch (GetFileType (h)) | ||||||
|  | 	{ | ||||||
|  | 		case FILE_TYPE_PIPE: | ||||||
|  | 			if (!once_only) | ||||||
|  | 			{ | ||||||
|  | 				NtQueryInformationFile = (PNtQueryInformationFile) | ||||||
|  | 				                         GetProcAddress (GetModuleHandle ("ntdll.dll"), | ||||||
|  | 				                                 "NtQueryInformationFile"); | ||||||
|  | 				once_only = TRUE; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			happened = 0; | ||||||
|  | 			if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0) | ||||||
|  | 			{ | ||||||
|  | 				if (avail) | ||||||
|  | 					happened |= *p_sought & (POLLIN | POLLRDNORM); | ||||||
|  | 			} | ||||||
|  | 			else if (GetLastError () == ERROR_BROKEN_PIPE) | ||||||
|  | 				happened |= POLLHUP; | ||||||
|  |  | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				/* It was the write-end of the pipe.  Check if it is writable. | ||||||
|  | 				   If NtQueryInformationFile fails, optimistically assume the pipe is | ||||||
|  | 				   writable.  This could happen on Windows 9x, where | ||||||
|  | 				   NtQueryInformationFile is not available, or if we inherit a pipe | ||||||
|  | 				   that doesn't permit FILE_READ_ATTRIBUTES access on the write end | ||||||
|  | 				   (I think this should not happen since Windows XP SP2; WINE seems | ||||||
|  | 				   fine too).  Otherwise, ensure that enough space is available for | ||||||
|  | 				   atomic writes.  */ | ||||||
|  | 				memset (&iosb, 0, sizeof (iosb)); | ||||||
|  | 				memset (&fpli, 0, sizeof (fpli)); | ||||||
|  |  | ||||||
|  | 				if (!NtQueryInformationFile | ||||||
|  | 				        || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), | ||||||
|  | 				                                   FilePipeLocalInformation) | ||||||
|  | 				        || fpli.WriteQuotaAvailable >= PIPE_BUF | ||||||
|  | 				        || (fpli.OutboundQuota < PIPE_BUF && | ||||||
|  | 				            fpli.WriteQuotaAvailable == fpli.OutboundQuota)) | ||||||
|  | 					happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | ||||||
|  | 			} | ||||||
|  | 			return happened; | ||||||
|  |  | ||||||
|  | 		case FILE_TYPE_CHAR: | ||||||
|  | 			ret = WaitForSingleObject (h, 0); | ||||||
|  | 			if (!IsConsoleHandle (h)) | ||||||
|  | 				return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0; | ||||||
|  |  | ||||||
|  | 			nbuffer = avail = 0; | ||||||
|  | 			bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); | ||||||
|  | 			if (bRet) | ||||||
|  | 			{ | ||||||
|  | 				/* Input buffer.  */ | ||||||
|  | 				*p_sought &= POLLIN | POLLRDNORM; | ||||||
|  | 				if (nbuffer == 0) | ||||||
|  | 					return POLLHUP; | ||||||
|  | 				if (!*p_sought) | ||||||
|  | 					return 0; | ||||||
|  |  | ||||||
|  | 				irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); | ||||||
|  | 				bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); | ||||||
|  | 				if (!bRet || avail == 0) | ||||||
|  | 					return POLLHUP; | ||||||
|  |  | ||||||
|  | 				for (i = 0; i < avail; i++) | ||||||
|  | 					if (irbuffer[i].EventType == KEY_EVENT) | ||||||
|  | 						return *p_sought; | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				/* Screen buffer.  */ | ||||||
|  | 				*p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND; | ||||||
|  | 				return *p_sought; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 		default: | ||||||
|  | 			ret = WaitForSingleObject (h, 0); | ||||||
|  | 			if (ret == WAIT_OBJECT_0) | ||||||
|  | 				return *p_sought & ~(POLLPRI | POLLRDBAND); | ||||||
|  |  | ||||||
|  | 			return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Convert fd_sets returned by select into revents values.  */ | ||||||
|  |  | ||||||
|  | static int windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents) | ||||||
|  | { | ||||||
|  | 	int happened = 0; | ||||||
|  |  | ||||||
|  | 	if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT) | ||||||
|  | 		happened |= (POLLIN | POLLRDNORM) & sought; | ||||||
|  |  | ||||||
|  | 	else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) | ||||||
|  | 	{ | ||||||
|  | 		int r, error; | ||||||
|  |  | ||||||
|  | 		char data[64]; | ||||||
|  | 		WSASetLastError (0); | ||||||
|  | 		r = recv (h, data, sizeof (data), MSG_PEEK); | ||||||
|  | 		error = WSAGetLastError (); | ||||||
|  | 		WSASetLastError (0); | ||||||
|  |  | ||||||
|  | 		if (r > 0 || error == WSAENOTCONN) | ||||||
|  | 			happened |= (POLLIN | POLLRDNORM) & sought; | ||||||
|  |  | ||||||
|  | 		/* Distinguish hung-up sockets from other errors.  */ | ||||||
|  | 		else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET | ||||||
|  | 		         || error == WSAECONNABORTED || error == WSAENETRESET) | ||||||
|  | 			happened |= POLLHUP; | ||||||
|  |  | ||||||
|  | 		else | ||||||
|  | 			happened |= POLLERR; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (lNetworkEvents & (FD_WRITE | FD_CONNECT)) | ||||||
|  | 		happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought; | ||||||
|  |  | ||||||
|  | 	if (lNetworkEvents & FD_OOB) | ||||||
|  | 		happened |= (POLLPRI | POLLRDBAND) & sought; | ||||||
|  |  | ||||||
|  | 	return happened; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int poll (struct pollfd *pfd, nfds_t nfd, int timeout) | ||||||
|  | { | ||||||
|  | 	static struct timeval tv0; | ||||||
|  | 	static HANDLE hEvent; | ||||||
|  | 	WSANETWORKEVENTS ev; | ||||||
|  | 	HANDLE h, handle_array[FD_SETSIZE + 2]; | ||||||
|  | 	DWORD ret, wait_timeout, nhandles; | ||||||
|  | 	fd_set rfds, wfds, xfds; | ||||||
|  | 	BOOL poll_again; | ||||||
|  | 	MSG msg; | ||||||
|  | 	int rc = 0; | ||||||
|  | 	nfds_t i; | ||||||
|  |  | ||||||
|  | 	if (nfd < 0 || timeout < -1) | ||||||
|  | 	{ | ||||||
|  | 		errno = EINVAL; | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!hEvent) | ||||||
|  | 		hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||||||
|  |  | ||||||
|  | restart: | ||||||
|  | 	handle_array[0] = hEvent; | ||||||
|  | 	nhandles = 1; | ||||||
|  | 	FD_ZERO (&rfds); | ||||||
|  | 	FD_ZERO (&wfds); | ||||||
|  | 	FD_ZERO (&xfds); | ||||||
|  |  | ||||||
|  | 	/* Classify socket handles and create fd sets. */ | ||||||
|  | 	for (i = 0; i < nfd; i++) | ||||||
|  | 	{ | ||||||
|  | 		int sought = pfd[i].events; | ||||||
|  | 		pfd[i].revents = 0; | ||||||
|  | 		if (pfd[i].fd < 0) | ||||||
|  | 			continue; | ||||||
|  | 		if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND | ||||||
|  | 		                | POLLPRI | POLLRDBAND))) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		h = (HANDLE)_get_osfhandle (pfd[i].fd); | ||||||
|  | 		if (IsSocketHandle (h)) | ||||||
|  | 		{ | ||||||
|  | 			int requested = FD_CLOSE; | ||||||
|  |  | ||||||
|  | 			/* see above; socket handles are mapped onto select.  */ | ||||||
|  | 			if (sought & (POLLIN | POLLRDNORM)) | ||||||
|  | 			{ | ||||||
|  | 				requested |= FD_READ | FD_ACCEPT; | ||||||
|  | 				FD_SET ((SOCKET) h, &rfds); | ||||||
|  | 			} | ||||||
|  | 			if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND)) | ||||||
|  | 			{ | ||||||
|  | 				requested |= FD_WRITE | FD_CONNECT; | ||||||
|  | 				FD_SET ((SOCKET) h, &wfds); | ||||||
|  | 			} | ||||||
|  | 			if (sought & (POLLPRI | POLLRDBAND)) | ||||||
|  | 			{ | ||||||
|  | 				requested |= FD_OOB; | ||||||
|  | 				FD_SET ((SOCKET) h, &xfds); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (requested) | ||||||
|  | 				WSAEventSelect ((SOCKET) h, hEvent, requested); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			/* Poll now.  If we get an event, do not poll again.  Also, | ||||||
|  | 			   screen buffer handles are waitable, and they'll block until | ||||||
|  | 			   a character is available.  windows_compute_revents eliminates | ||||||
|  | 			   bits for the "wrong" direction. */ | ||||||
|  | 			pfd[i].revents = windows_compute_revents (h, &sought); | ||||||
|  | 			if (sought) | ||||||
|  | 				handle_array[nhandles++] = h; | ||||||
|  | 			if (pfd[i].revents) | ||||||
|  | 				timeout = 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (select (0, &rfds, &wfds, &xfds, &tv0) > 0) | ||||||
|  | 	{ | ||||||
|  | 		/* Do MsgWaitForMultipleObjects anyway to dispatch messages, but | ||||||
|  | 		   no need to call select again.  */ | ||||||
|  | 		poll_again = FALSE; | ||||||
|  | 		wait_timeout = 0; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		poll_again = TRUE; | ||||||
|  | 		if (timeout == INFTIM) | ||||||
|  | 			wait_timeout = INFINITE; | ||||||
|  | 		else | ||||||
|  | 			wait_timeout = timeout; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (;;) | ||||||
|  | 	{ | ||||||
|  | 		ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, | ||||||
|  | 		                                 wait_timeout, QS_ALLINPUT); | ||||||
|  |  | ||||||
|  | 		if (ret == WAIT_OBJECT_0 + nhandles) | ||||||
|  | 		{ | ||||||
|  | 			/* new input of some other kind */ | ||||||
|  | 			BOOL bRet; | ||||||
|  | 			while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) | ||||||
|  | 			{ | ||||||
|  | 				TranslateMessage (&msg); | ||||||
|  | 				DispatchMessage (&msg); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (poll_again) | ||||||
|  | 		select (0, &rfds, &wfds, &xfds, &tv0); | ||||||
|  |  | ||||||
|  | 	/* Place a sentinel at the end of the array.  */ | ||||||
|  | 	handle_array[nhandles] = NULL; | ||||||
|  | 	nhandles = 1; | ||||||
|  | 	for (i = 0; i < nfd; i++) | ||||||
|  | 	{ | ||||||
|  | 		int happened; | ||||||
|  |  | ||||||
|  | 		if (pfd[i].fd < 0) | ||||||
|  | 			continue; | ||||||
|  | 		if (!(pfd[i].events & (POLLIN | POLLRDNORM | | ||||||
|  | 		                       POLLOUT | POLLWRNORM | POLLWRBAND))) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		h = (HANDLE) _get_osfhandle (pfd[i].fd); | ||||||
|  | 		if (h != handle_array[nhandles]) | ||||||
|  | 		{ | ||||||
|  | 			/* It's a socket.  */ | ||||||
|  | 			WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); | ||||||
|  | 			WSAEventSelect ((SOCKET) h, 0, 0); | ||||||
|  |  | ||||||
|  | 			/* If we're lucky, WSAEnumNetworkEvents already provided a way | ||||||
|  | 			   to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */ | ||||||
|  | 			if (FD_ISSET ((SOCKET) h, &rfds) && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT))) | ||||||
|  | 				ev.lNetworkEvents |= FD_READ | FD_ACCEPT; | ||||||
|  | 			if (FD_ISSET ((SOCKET) h, &wfds)) | ||||||
|  | 				ev.lNetworkEvents |= FD_WRITE | FD_CONNECT; | ||||||
|  | 			if (FD_ISSET ((SOCKET) h, &xfds)) | ||||||
|  | 				ev.lNetworkEvents |= FD_OOB; | ||||||
|  |  | ||||||
|  | 			happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events, ev.lNetworkEvents); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			/* Not a socket.  */ | ||||||
|  | 			int sought = pfd[i].events; | ||||||
|  | 			happened = windows_compute_revents (h, &sought); | ||||||
|  | 			nhandles++; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ((pfd[i].revents |= happened) != 0) rc++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!rc && timeout == INFTIM) | ||||||
|  | 	{ | ||||||
|  | 		SleepEx (1, TRUE); | ||||||
|  | 		goto restart; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return rc; | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								moo/lib/poll-msw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								moo/lib/poll-msw.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | #ifndef _POLL_MSW_H_ | ||||||
|  | #define _POLL_MSW_H_ | ||||||
|  |  | ||||||
|  | #include "moo.h" | ||||||
|  |  | ||||||
|  | /* Event types that can be polled for.  These bits may be set in `events' | ||||||
|  |    to indicate the interesting event types; they will appear in `revents' | ||||||
|  |    to indicate the status of the file descriptor.  */ | ||||||
|  | #define POLLIN          0x001           /* There is data to read.  */ | ||||||
|  | #define POLLPRI         0x002           /* There is urgent data to read.  */ | ||||||
|  | #define POLLOUT         0x004           /* Writing now will not block.  */ | ||||||
|  |  | ||||||
|  | /* Event types always implicitly polled for.  These bits need not be set in | ||||||
|  |    `events', but they will appear in `revents' to indicate the status of | ||||||
|  |    the file descriptor.  */ | ||||||
|  | #define POLLERR         0x008           /* Error condition.  */ | ||||||
|  | #define POLLHUP         0x010           /* Hung up.  */ | ||||||
|  | #define POLLNVAL        0x020           /* Invalid polling request.  */ | ||||||
|  |  | ||||||
|  | /* Data structure describing a polling request.  */ | ||||||
|  | struct pollfd  | ||||||
|  | { | ||||||
|  | 	int fd;                     /* File descriptor to poll.  */ | ||||||
|  | 	short int events;           /* Types of events poller cares about.  */ | ||||||
|  | 	short int revents;          /* Types of events that actually occurred.  */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Poll the file descriptors described by the NFDS structures starting at | ||||||
|  |    FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for | ||||||
|  |    an event to occur; if TIMEOUT is -1, block until an event occurs. | ||||||
|  |    Returns the number of file descriptors with events, zero if timed out, | ||||||
|  |    or -1 for errors.  */ | ||||||
|  |  | ||||||
|  | typedef unsigned long nfds_t; | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | int poll (struct pollfd *pfd, nfds_t nfd, int timeout); | ||||||
|  |  | ||||||
|  | #if defined(__cplusplus) | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user