THRIFT-1512 Thrift socket support for Windows XP
Patch: Peace C

git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1241171 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/windows/config.h b/lib/cpp/src/windows/config.h
index 79168cf..c4bf9f3 100644
--- a/lib/cpp/src/windows/config.h
+++ b/lib/cpp/src/windows/config.h
@@ -59,8 +59,8 @@
 #	include <pthread.h>
 #else
 struct timespec {
-	int64_t tv_sec;
-	int64_t tv_nsec;
+  int64_t tv_sec;
+  int64_t tv_nsec;
 };
 #	define USE_BOOST_THREAD 1
 #	define ctime_r( _clock, _buf ) \
@@ -78,44 +78,73 @@
     return 0;
 }
 
-#if WINVER <= 0x0502
+#if WINVER <= 0x0502 //XP, Server2003
+#define POLLIN  0x0300
+#define POLLOUT 0x0010
 #define poll(fds, nfds, timeout) \
     poll_win32(fds, nfds, timeout)
 
 typedef struct pollfd {
-
-    SOCKET  fd;
-    SHORT   events;
-    SHORT   revents;
-
+  SOCKET  fd;
+  SHORT   events;
+  SHORT   revents;
 } WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD;
 
-inline int poll_win32(LPWSAPOLLFD fdArray, ULONG /*fds*/, INT timeout)
+inline int poll_win32(LPWSAPOLLFD fdArray, ULONG nfds, INT timeout)
 {
-    fd_set read_fds;
-    fd_set write_fds;
-    fd_set except_fds;
+  fd_set read_fds, write_fds;
+  fd_set* read_fds_ptr  = NULL;
+  fd_set* write_fds_ptr = NULL;
 
-    FD_ZERO(&read_fds);
-    FD_ZERO(&write_fds);
-    FD_ZERO(&except_fds);
+  FD_ZERO(&read_fds);
+  FD_ZERO(&write_fds);
 
-    FD_SET(fdArray[0].fd, &read_fds);
-    FD_SET(fdArray[0].fd, &write_fds);
-    FD_SET(fdArray[0].fd, &except_fds);
+  for(ULONG i=0; i<nfds; i++) {
+    //Read (in) socket
+    if((fdArray[i].events & POLLIN) == POLLIN) {
+      read_fds_ptr = &read_fds;
+      FD_SET(fdArray[i].fd, &read_fds);
+    }
+    //Write (out) socket
+    else if((fdArray[i].events & POLLOUT) == POLLOUT) {
+      write_fds_ptr = &write_fds;
+      FD_SET(fdArray[i].fd, &write_fds);
+    }
+  }
 
+  timeval time_out;
+  timeval* time_out_ptr = NULL;
+  if(timeout >= 0) {
     timeval time_out = {timeout / 1000, timeout * 1000};
-    return select(1, &read_fds, &write_fds, &except_fds, &time_out);
+    time_out_ptr = &time_out;
+  }
+  else { //to avoid compiler warnings
+    (void)time_out;
+    (void)timeout;
+  }
+
+  int sktready = select(1, read_fds_ptr, write_fds_ptr, NULL, time_out_ptr);
+  if(sktready > 0) {
+    for(ULONG i=0; i<read_fds.fd_count; i++) {
+      if(FD_ISSET(fdArray[i].fd, &read_fds))
+        fdArray[i].revents = POLLIN;
+    }
+    for(ULONG i=0; i<write_fds.fd_count; i++) {
+      if(FD_ISSET(fdArray[i].fd, &write_fds))
+        fdArray[i].revents = POLLOUT;
+    }
+  }
+  return sktready;
 }
-#else
-	inline int poll(struct pollfd* fdArray, ULONG fds, INT timeout) {
-		return WSAPoll(fdArray, fds, timeout);
-	}
+#else //Vista, Win7...
+  inline int poll(struct pollfd* fdArray, ULONG fds, INT timeout) {
+    return WSAPoll(fdArray, fds, timeout);
+  }
 #endif // WINVER
 
-inline int close(SOCKET socket)
+inline void close(SOCKET socket)
 {
-    return ::closesocket(socket);
+    ::closesocket(socket);
 }
 
 #endif // _THRIFT_WINDOWS_CONFIG_H_