Win32OperatingSystem.st
changeset 16315 b08c60b1588d
parent 16309 6df7a4841fb6
child 16321 6e24f3c5ba96
--- a/Win32OperatingSystem.st	Thu Apr 10 17:18:38 2014 +0200
+++ b/Win32OperatingSystem.st	Thu Apr 10 17:38:13 2014 +0200
@@ -11128,19 +11128,20 @@
      Thus, the caller can simply scan these arrays upTo the end or a nil value."
 
 %{
+//#define SELECTDEBUGWIN32
+//#define SELECT3DEBUGWIN32
 #define MAXHANDLE 128
     int i;
     INT t;
     OBJ fd, retFd;
-    int ret;
     int numHandles = 0;
     DWORD res;
     HANDLE hArray[MAXHANDLE+1];
     int retArray[MAXHANDLE];
     int readCount, writeCount, exceptCount;
-    int resultSizeReadable, resultSizeWritable, resultSizeException;
-    int cntR = 0, cntW = 0, cntE = 0;
-    OBJ *__resultR, *__resultW, *__resultE;
+    int resultSizeReadable = 0, resultSizeWritable = 0, resultSizeException = 0;
+    int cntR = 0, cntW = 0, cntE = 0, cntAll = 0;
+    int *pcntR = &cntR, *pcntW = &cntW, *pcntE = &cntE;
 
     if (readableResultFdArray != nil) {
         if (! __isArrayLike(readableResultFdArray)) {
@@ -11153,12 +11154,22 @@
             goto fail;
         }
         resultSizeWritable = __arraySize(writableResultFdArray);
+        if (readableResultFdArray == writableResultFdArray) {
+            // allow common result set for read/write/except
+            pcntW = &cntR;
+        }
     }
     if (exceptionResultFdArray != nil) {
         if (! __isArrayLike(exceptionResultFdArray)) {
             goto fail;
         }
         resultSizeException = __arraySize(exceptionResultFdArray);
+        if (exceptionResultFdArray == readableResultFdArray) {
+            // allow common result set for read/write/except
+            pcntE = &cntR;
+        } else if (exceptionResultFdArray == writableResultFdArray) {
+            pcntE = &cntW;
+        }
     }
 
     if (__isNonNilObject(readFdArray)) {
@@ -11181,9 +11192,6 @@
     } else {
         exceptCount = 0;
     }
-    __resultR = __arrayVal(readableResultFdArray);
-    __resultW = __arrayVal(writableResultFdArray);
-    __resultE = __arrayVal(exceptionResultFdArray);
 
     for (i = 0; (i < readCount) && (numHandles < MAXHANDLE); i++) {
         fd = __arrayVal(readFdArray)[i];
@@ -11194,13 +11202,13 @@
                 retArray[numHandles] = i;
                 ++numHandles;
             } else {
-                int canRead = _canReadWithoutBlocking (__intVal(fd) );
+                int canRead = _canReadWithoutBlocking(__intVal(fd));
 
                 if (canRead > 0 ) {
-                    if (cntR < resultSizeReadable) {
-                        __resultR[cntR] = fd;
+                    if (*pcntR < resultSizeReadable) {
+                        __arrayVal(readableResultFdArray)[*pcntR] = fd;
                     }
-                    cntR++;
+                    (*pcntR)++; cntAll++;
                 } else {
                     if (canRead < 0 ) {
                         @global(LastErrorNumber) = __mkSmallInteger(EBADF);
@@ -11220,13 +11228,13 @@
                 retArray[numHandles] = i + 10000;
                 ++numHandles;
             } else {
-                int canWrite = _canWriteWithoutBlocking (__intVal(fd) );
+                int canWrite = _canWriteWithoutBlocking(__intVal(fd));
 
                 if (canWrite > 0 ) {
-                    if (cntW < resultSizeWritable) {
-                        __resultW[cntW] = fd;
+                    if (*pcntW < resultSizeWritable) {
+                        __arrayVal(writableResultFdArray)[*pcntW] = fd;
                     }
-                    cntW++;
+                    (*pcntW)++; cntAll++;
                 } else {
                     if (canWrite < 0 ) {
                         @global(LastErrorNumber) = __mkSmallInteger(EBADF);
@@ -11237,7 +11245,7 @@
         }
     }
 
-    for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE);i++) {
+    for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE); i++) {
         fd = __arrayVal(exceptFdArray)[i];
 
         if (fd != nil) {
@@ -11249,10 +11257,8 @@
         }
     }
 
-    if (cntR || cntW) {
-        // for now: we are done
-        RETURN(__mkSmallInteger(cntR+cntW+cntE));
-        // maybe later: check for other handles immediately
+    if (cntAll) {
+        // check for other handles immediately, no timeout
         t = 0;
     } else {
         if (__isSmallInteger(millis)) {
@@ -11266,106 +11272,107 @@
         }
     }
 
+    if (numHandles == 0 && t == 0) {
+        // nothing to do and no wait
+        goto done;
+    }
+
 #ifdef SELECT3DEBUGWIN32
-    console_printf("wait Handles = %d timeout = %d\n",numHandles, t);
+    console_printf("wait numhandles = %d timeout = %d\n", numHandles, t);
 #endif
 
     res = __vmWait(numHandles, hArray, MAXHANDLE, t);
 
-    // refetch possibly moved pointers after wait
-    __resultR = __arrayVal(readableResultFdArray);
-    __resultW = __arrayVal(writableResultFdArray);
-    __resultE = __arrayVal(exceptionResultFdArray);
+    if (res == WAIT_TIMEOUT) {
+#ifdef SELECT3DEBUGWIN32
+        console_printf("- timeOut; ret nil\n" );
+#endif
+        if (t = 0)
+            goto done;
+        else
+            goto polling;
+    }
+    if (res == WAIT_FAILED) {
+#ifdef SELECT2DEBUGWIN32
+        console_printf("- error %d; ret nil\n", GetLastError());
+#endif
+        if (__threadErrno == EINTR) {
+            @global(LastErrorNumber) = nil;
+            RETURN (__mkSmallInteger(0));
+        } else {
+            if (@global(InfoPrinting) == true) {
+                console_fprintf(stderr, "Win32OS [info]: select errno = %d\n", __threadErrno);
+            }
+            @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+            RETURN (__mkSmallInteger(-1));
+        }
+    }
 
     if (numHandles) {
-        if (res == WAIT_FAILED) {
-#ifdef SELECT2DEBUGWIN32
-            console_printf("- error %d; ret nil\n",GetLastError());
-#endif
-            if (__threadErrno == EINTR) {
-                @global(LastErrorNumber) = nil;
-                RETURN (__mkSmallInteger(0));
-            } else {
-                if (@global(InfoPrinting) == true) {
-                    console_fprintf(stderr, "Win32OS [info]: select errno = %d\n", __threadErrno);
-                }
-                @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-                RETURN (__mkSmallInteger(-1));
-            }
-        }
-
-        if (res == WAIT_TIMEOUT) {
-#ifdef SELECT3DEBUGWIN32
-            console_printf("- timeOut; ret nil\n" );
-#endif
-            goto polling;
-        }
-
         if (res == numHandles) {
+            // vmwait() added an IRQ event to the handles, and this one has been triggered
             if (1 /* @global(InfoPrinting) == true */) {
                 console_fprintf(stderr, "Win32OS [info]: plugIn event has been handled\n");
             }
             goto done;
         }
         if ((res < 0) || (res > numHandles)) {
-#ifdef SELECTDEBUGWIN32
             console_printf("- res=%d error1 %d\n", res, GetLastError());
-#endif
             goto done;
         }
 
-        ret = res;
-
-        if (ret < numHandles) {
-            int fd = retArray[ret];
-
-            @global(LastErrorNumber) = nil;
-
+        fd = retArray[res];
 #ifdef SELECTDEBUGWIN32
-            if (ret) console_printf("wait Handles %d %d ret\n", ret, fd);
-#endif
-            if (fd < 10000) {
-                if (cntR < resultSizeReadable) {
-                    OBJ temp = __arrayVal(readFdArray)[fd];
-                    __resultR[cntR] = temp;
-                    __STORE(readableResultFdArray, temp);
-                }
-                cntR++;
+        console_printf("wait Handles res %d fd %d numHandles %d --- ", res, fd, numHandles);
+#endif
+        if (fd < 10000) {
+            if (*pcntR < resultSizeReadable) {
+                OBJ temp = __arrayVal(readFdArray)[fd];
+                __arrayVal(readableResultFdArray)[*pcntR] = temp;
+                __STORE(readableResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+                console_printf("read ready: %x\n", temp);
+#endif
             }
-            if (fd < 20000) {
-                if (cntW < resultSizeWritable) {
-                    OBJ temp = __arrayVal(writeFdArray)[fd-10000];
-                    __resultW[cntW] = temp;
-                    __STORE(writableResultFdArray, temp);
-                }
-                cntW++;
+            (*pcntR)++; cntAll++;
+        } else if (fd < 20000) {
+            if (*pcntW < resultSizeWritable) {
+                OBJ temp = __arrayVal(writeFdArray)[fd-10000];
+                __arrayVal(writableResultFdArray)[*pcntW] = temp;
+                __STORE(writableResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+                console_printf("write ready: %x\n", temp);
+#endif
             }
-            if (cntE < resultSizeException) {
+            (*pcntW)++; cntAll++;
+        } else {
+            if (*pcntE < resultSizeException) {
                 OBJ temp = __arrayVal(exceptFdArray)[fd-20000];
-                __resultE[cntE] = temp;
+                __arrayVal(exceptionResultFdArray)[*pcntE] = temp;
                 __STORE(exceptionResultFdArray, temp);
+#ifdef SELECTDEBUGWIN32
+                console_printf("except ready: %x\n", temp);
+#endif
             }
-            cntE++;
+            (*pcntE)++; cntAll++;
         }
-        console_fprintf(stderr, "Win32OS [info]: wait Handles ret = %d error2 %d\n", ret, GetLastError());
-        goto fail;
     }
     if (t == 0) {
-        // if we did not wait, there is no need to check again
+        // if we did not wait, there is no need to check sockets again
         goto done;
     }
 
 polling:
     for (i=0; i < readCount; i++) {
         fd = __arrayVal(readFdArray)[i];
-        if (fd != nil && ! __isExternalAddressLike(fd)) {
+        if (__isSmallInteger(fd)) {
             int canRead = _canReadWithoutBlocking (__intVal(fd));
 
             if (canRead > 0 ) {
-                if (cntR < resultSizeReadable) {
-                    __resultR[cntR] = fd;
+                if (*pcntR < resultSizeReadable) {
+                    __arrayVal(readableResultFdArray)[*pcntR] = fd;
                 }
-                cntR++;
+                (*pcntR)++; cntAll++;
             } else {
                 if (canRead < 0 ) {
                     @global(LastErrorNumber) = __mkSmallInteger(EBADF);
@@ -11375,16 +11382,16 @@
         }
     }
 
-    for (i=0; i < writeCount;i++) {
+    for (i=0; i < writeCount; i++) {
         fd = __arrayVal(writeFdArray)[i];
-        if (fd != nil && ! __isExternalAddressLike(fd)) {
+        if (__isSmallInteger(fd)) {
             int canWrite = _canWriteWithoutBlocking (__intVal(fd));
 
             if (canWrite > 0 ) {
-                if (cntW < resultSizeWritable) {
-                    __resultW[cntW] = __mkSmallInteger(i);
+                if (*pcntW < resultSizeWritable) {
+                    __arrayVal(writableResultFdArray)[*pcntW] = __mkSmallInteger(i);
                 }
-                cntW++;
+                (*pcntW)++; cntAll++;
             } else {
                 if (canWrite < 0 ) {
                     @global(LastErrorNumber) = __mkSmallInteger(EBADF);
@@ -11396,256 +11403,18 @@
 
 done:
     /* add a delimiter */
-    if (cntR < resultSizeReadable) {
-        __resultR[cntR] = nil;
-    }
-    if (cntW < resultSizeWritable) {
-        __resultW[cntW] = nil;
-    }
-    if (cntE < resultSizeException) {
-        __resultE[cntE] = nil;
+    if (*pcntR < resultSizeReadable) {
+        __arrayVal(readableResultFdArray)[*pcntR] = nil;
+    }
+    if (*pcntW < resultSizeWritable) {
+        __arrayVal(writableResultFdArray)[*pcntW] = nil;
+    }
+    if (*pcntE < resultSizeException) {
+        __arrayVal(exceptionResultFdArray)[*pcntE] = nil;
     }
 
     @global(LastErrorNumber) = nil;
-    RETURN (__mkSmallInteger(cntR+cntW+cntE));
-
-fail: ;
-%}.
-    "
-     timeout argument not integer,
-     or any fd-array nonNil and not an array
-     or not supported by OS
-    "
-    ^ self primitiveFailed
-!
-
-selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis
-    "wait for any fd in readFdArray (an Array of integers) to become ready for
-     reading, writeFdArray to become ready for writing, or exceptFdArray to
-     arrive exceptional data (i.e. out-of-band data).
-     Timeout after t milliseconds or, if the timeout time is 0, immediately..
-     Empty fd-sets will always wait. Zero time can be used to poll file-
-     descriptors (i.e. to check if I/O possible without blocking).
-     Return first ready fd if I/O ok, nil if timed-out or interrupted."
-
-%{
-#define MAXHANDLE 128
-
-    int i;
-    INT t;
-    OBJ fd, retFd;
-    int ret;
-    int numHandles = 0;
-    DWORD res;
-    HANDLE hArray[MAXHANDLE+1];
-    int    retArray[MAXHANDLE];
-    int    readCount;
-    int    writeCount;
-    int    exceptCount;
-
-    if (__isNonNilObject(readFdArray)) {
-	if (! __isArrayLike(readFdArray)) goto fail;
-	readCount = __arraySize(readFdArray);
-    } else {
-	readCount = 0;
-    }
-
-    if (__isNonNilObject(writeFdArray)) {
-	if (! __isArrayLike(writeFdArray)) goto fail;
-	writeCount = __arraySize(writeFdArray);
-    } else {
-	writeCount = 0;
-    }
-
-    if (__isNonNilObject(exceptFdArray)) {
-	if (! __isArrayLike(exceptFdArray)) goto fail;
-	exceptCount = __arraySize(exceptFdArray);
-    } else {
-	exceptCount = 0;
-    }
-
-    for (i = 0; (i < readCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(readFdArray)->a_element[i];
-
-	if (fd != nil) {
-	    if (__isExternalAddressLike(fd)) {
-		hArray  [numHandles] = _HANDLEVal(fd);
-		retArray[numHandles] = i;
-		++numHandles;
-	    } else {
-		int canRead = _canReadWithoutBlocking (__intVal(fd) );
-
-		if (canRead > 0 ) {
-		    RETURN (fd);
-		} else {
-		    if (canRead < 0 ) {
-			@global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			RETURN ( @symbol(error) );
-		    }
-		}
-	    }
-	}
-    }
-
-    for (i = 0; (i < writeCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(writeFdArray)->a_element[i];
-
-	if (fd != nil) {
-	    if (__isExternalAddressLike(fd)) {
-		hArray  [numHandles] = _HANDLEVal(fd);
-		retArray[numHandles] = i + 10000;
-		++numHandles;
-	    } else {
-		int canWrite = _canWriteWithoutBlocking (__intVal(fd) );
-
-		if (canWrite > 0 ) {
-		    RETURN (fd);
-		} else {
-		    if (canWrite < 0 ) {
-			@global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			RETURN ( @symbol(error) );
-		    }
-		}
-	    }
-	}
-    }
-
-    for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE);i++) {
-	fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
-
-	if (fd != nil) {
-	    if (__isExternalAddressLike(fd)) {
-		hArray  [numHandles] = _HANDLEVal(fd);
-		retArray[numHandles] = i + 20000;
-		++numHandles;
-	    }
-	}
-    }
-
-    if (__isSmallInteger(millis)) {
-	t = __intVal(millis);
-
-	if (t <= 0 && numHandles == 0) {
-	    RETURN (nil);
-	}
-    } else {
-	t = INFINITE;
-    }
-
-#ifdef SELECT3DEBUGWIN32
-    console_printf("wait Handles = %d timeout = %d\n",numHandles, t);
-#endif
-
-    res = __vmWait (numHandles, hArray, MAXHANDLE, t);
-
-    if (numHandles) {
-	if (res == WAIT_FAILED) {
-#ifdef SELECT2DEBUGWIN32
-	    console_printf("- error %d; ret nil\n",GetLastError());
-#endif
-	    if (__threadErrno == EINTR) {
-		__threadErrno = 0;
-		@global(LastErrorNumber) = nil;
-	    } else {
-		__threadErrno = EBADF;
-		if (@global(InfoPrinting) == true) {
-		    console_fprintf(stderr, "Win32OS [info]: select errno = %d\n", __threadErrno);
-		}
-		@global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
-		RETURN ( @symbol(error) );
-	    }
-	    RETURN ( nil );
-	}
-
-	if (res == WAIT_TIMEOUT) {
-#ifdef SELECT3DEBUGWIN32
-	    console_printf("- timeOut; ret nil\n" );
-#endif
-	    goto polling;
-	}
-
-	if (res == numHandles) {
-	    if (1 /* @global(InfoPrinting) == true */) {
-		console_fprintf(stderr, "Win32OS [info]: plugIn event has been handled\n");
-	    }
-	    __threadErrno = 0;
-	    @global(LastErrorNumber) = nil;
-	    RETURN ( nil );
-	}
-	if ((res < 0) || (res > numHandles)) {
-#ifdef SELECTDEBUGWIN32
-	    console_printf("- res=%d error1 %d\n", res, GetLastError());
-#endif
-	    __threadErrno = 0;
-	    @global(LastErrorNumber) = nil;
-	    RETURN ( nil );
-	}
-
-	ret = res;
-
-	if (ret < numHandles) {
-	    int fd = retArray[ret];
-
-	    @global(LastErrorNumber) = nil;
-
-#ifdef SELECTDEBUGWIN32
-	    if (ret) console_printf("wait Handles %d %d ret\n", ret, fd);
-#endif
-	    if (fd < 10000) {
-		RETURN ( __ArrayInstPtr(readFdArray)->a_element[fd] );
-	    }
-	    if (fd < 20000) {
-		RETURN ( __ArrayInstPtr(writeFdArray)->a_element[fd-10000] );
-	    }
-	    RETURN ( __ArrayInstPtr(exceptFdArray)->a_element[fd-20000] );
-	}
-	console_fprintf(stderr, "Win32OS [info]: wait Handles ret = %d error2 %d\n", ret, GetLastError());
-	goto fail;
-    } else {
-
-polling:
-
-	for (i=0; i < readCount;i++) {
-	    fd = __ArrayInstPtr(readFdArray)->a_element[i];
-
-	    if (fd != nil) {
-		if (! __isExternalAddressLike(fd)) {
-		    int canRead = _canReadWithoutBlocking (__intVal(fd));
-
-		    if (canRead > 0 ) {
-			RETURN (fd);
-		    } else {
-			if (canRead < 0 ) {
-			    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			    RETURN ( @symbol(error) );
-			}
-		    }
-		}
-	    }
-	}
-
-	for (i=0; i < writeCount;i++) {
-	    fd = __ArrayInstPtr(writeFdArray)->a_element[i];
-
-	    if (fd != nil) {
-		if (! __isExternalAddressLike(fd)) {
-		    int canWrite = _canWriteWithoutBlocking (__intVal(fd));
-
-		    if (canWrite > 0 ) {
-			RETURN (fd);
-		    } else {
-			if (canWrite < 0 ) {
-			    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-			    RETURN ( @symbol(error) );
-			}
-		    }
-		}
-	    }
-	}
-
-	@global(LastErrorNumber) = nil;
-	RETURN ( nil );
-    }
+    RETURN (__mkSmallInteger(cntAll));
 
 fail: ;
 %}.
@@ -17857,15 +17626,15 @@
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.496 2014-04-10 15:38:13 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.496 2014-04-10 15:38:13 stefan Exp $'
 !
 
 version_SVN
-    ^ '$Id: Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
+    ^ '$Id: Win32OperatingSystem.st,v 1.496 2014-04-10 15:38:13 stefan Exp $'
 
 ! !