diff -r 3b069e0219c6 -r b08c60b1588d Win32OperatingSystem.st --- 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 $' ! !