fix Windows socket poll
Stefan Schuermans

Stefan Schuermans commited on 2017-10-28 22:57:32
Showing 3 changed files, with 47 additions and 4 deletions.

... ...
@@ -21,33 +21,47 @@ namespace Blinker {
21 21
  */
22 22
 void Io::wait(Set &read, Set &write, const Time &timeout)
23 23
 {
24
-  // get read set and write set
24
+  // get read set and write set, also count entries
25
+  unsigned int rds = 0;
25 26
   fd_set fd_rd;
26 27
   FD_ZERO(&fd_rd);
27 28
   for (Set::const_iterator it = read.begin(); it != read.end(); ++it) {
28 29
     if ((*it)->m_socket != INVALID_SOCKET) {
29 30
       FD_SET((*it)->m_socket, &fd_rd);
31
+      ++rds;
30 32
     }
31 33
   }
34
+  unsigned int wrs = 0;
32 35
   fd_set fd_wr;
33 36
   FD_ZERO(&fd_wr);
34 37
   for (Set::const_iterator it = write.begin(); it != write.end(); ++it) {
35 38
     if ((*it)->m_socket != INVALID_SOCKET) {
36 39
       FD_SET((*it)->m_socket, &fd_wr);
40
+      ++wrs;
37 41
     }
38 42
   }
39 43
 
44
+  /* special case for no sockets to check,
45
+     because select does not work for allsets empty on Windows */
46
+  if (rds == 0 && wrs == 0) {
47
+    if (timeout <= Time::zero) {
48
+      return;
49
+    }
50
+    Sleep(timeout.toMs());
51
+  }
52
+
40 53
   // get timeout
41 54
   struct timeval to;
42
-  if (timeout < Time::zero) // don't use negaitve timeout
55
+  if (timeout < Time::zero) { // don't use negative timeout
43 56
     Time::zero.toTimeval(to);
44
-  else
57
+  } else {
45 58
     timeout.toTimeval(to);
59
+  }
46 60
 
47 61
   // wait for I/O event on sockets
48 62
   fd_set fd_err;
49 63
   FD_ZERO(&fd_err);
50
-  int res = select(0 /* ignore on Windows */, &fd_rd, &fd_wr, &fd_err, &to);
64
+  int res = select(0 /* ignored on Windows */, &fd_rd, &fd_wr, &fd_err, &to);
51 65
 
52 66
   // error or timeout
53 67
   if (res <= 0) {
... ...
@@ -179,6 +179,29 @@ float Time::toFloatSec() const
179 179
   return m_sec + m_ns * 1.0e-9f;
180 180
 }
181 181
 
182
+/**
183
+ * @brief convert to milliseconds
184
+ * @return milliseconds
185
+ */
186
+int Time::toMs() const
187
+{
188
+  if (m_sec > INT_MAX / 1000) {
189
+    return INT_MAX;
190
+  }
191
+  if (m_sec < INT_MIN / 1000) {
192
+    return INT_MIN;
193
+  }
194
+  int ms = m_sec * 1000;
195
+  int ms2 = m_ns / 1000000;
196
+  if (ms2 > 0 && ms > INT_MAX - ms2) {
197
+    return INT_MAX;
198
+  }
199
+  if (ms2 < 0 && ms < INT_MIN - ms2) {
200
+    return INT_MIN;
201
+  }
202
+  return ms + ms2;
203
+}
204
+
182 205
 /**
183 206
  * @brief convert to struct timeval
184 207
  * @param[out] tv struct timeval
... ...
@@ -79,6 +79,12 @@ public:
79 79
    */
80 80
   float toFloatSec() const;
81 81
 
82
+  /**
83
+   * @brief convert to milliseconds
84
+   * @return milliseconds
85
+   */
86
+  int toMs() const;
87
+
82 88
   /**
83 89
    * @brief convert to struct timeval
84 90
    * @param[out] tv struct timeval
85 91