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/README_WINDOWS b/lib/cpp/README_WINDOWS
index 3a00b3a..a955949 100644
--- a/lib/cpp/README_WINDOWS
+++ b/lib/cpp/README_WINDOWS
@@ -75,6 +75,13 @@
 If you wanted instead to link with boost thread as a shared library,
 you'll need to uncomment those two lines, and recompile.
 
+Windows version compatibility
+=============================
+The Thrift library targets Windows XP for broadest compatbility. A notable
+difference is in the Windows-specific implementation of the socket poll
+function. To target Vista, Win7 or other versions, comment out the line
+#define TARGET_WIN_XP.
+
 Known issues
 ============
 
diff --git a/lib/cpp/src/windows/TargetVersion.h b/lib/cpp/src/windows/TargetVersion.h
index 8c392fc..35c093f 100644
--- a/lib/cpp/src/windows/TargetVersion.h
+++ b/lib/cpp/src/windows/TargetVersion.h
@@ -28,8 +28,4 @@
 #error This is a MSVC header only.
 #endif
 
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0601
-#endif
-
 #endif //_THIRFT_WINDOWS_TARGETVERSION_H_
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_
diff --git a/lib/cpp/src/windows/force_inc.h b/lib/cpp/src/windows/force_inc.h
index 2ee0207..803d132 100644
--- a/lib/cpp/src/windows/force_inc.h
+++ b/lib/cpp/src/windows/force_inc.h
@@ -18,19 +18,29 @@
  */
 
 #ifndef _THRIFT_WINDOWS_FORCEINC_H_
-#define _THRIFT_WINDOWS_FORCEINC_H_
+#  define _THRIFT_WINDOWS_FORCEINC_H_
 
 #if defined(_MSC_VER) && (_MSC_VER > 1200)
-#pragma once
+#  pragma once
 #endif // _MSC_VER
 
 #ifndef _WIN32
-#error This is a MSVC header only.
+#  error This is a MSVC header only.
 #endif
 
 #define NOMINMAX
 #define BOOST_ALL_NO_LIB 1
 #define BOOST_THREAD_NO_LIB 1
+#define TARGET_WIN_XP
+
+#ifdef TARGET_WIN_XP
+#  define WINVER 0x0501
+#  define _WIN32_WINNT 0x0501
+#endif
+
+#ifndef _WIN32_WINNT
+#  define _WIN32_WINNT 0x0601
+#endif
 
 #include "windows/config.h"