--- 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 $'
! !