--- a/Win32OperatingSystem.st Wed Apr 09 23:10:05 2014 +0200
+++ b/Win32OperatingSystem.st Thu Apr 10 10:54:27 2014 +0200
@@ -11110,6 +11110,315 @@
^ (self readCheck:fd) ifTrue:[1] ifFalse:[0]
!
+selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray
+ readableInto:readableResultFdArray writableInto:writableResultFdArray exceptionInto:exceptionResultFdArray
+ 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).
+ The corresponding filedescriptors which are ready are returned in readableResultFdArray,
+ writableResultFdArray and exceptionResultFdArray respectively.
+
+ Return the (overall) number of selected filedescriptors.
+ readableResultFdArray, writableResultFdArray and exceptionResultFdArray will
+ get a nil-value stored into the slot after the last valid fileDescriptor;
+ Thus, the caller can simply scan these arrays upTo the end or a nil value."
+
+%{
+#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;
+
+ if (readableResultFdArray != nil) {
+ if (! __isArrayLike(readableResultFdArray)) {
+ goto fail;
+ }
+ resultSizeReadable = __arraySize(readableResultFdArray);
+ }
+ if (writableResultFdArray != nil) {
+ if (! __isArrayLike(writableResultFdArray)) {
+ goto fail;
+ }
+ resultSizeWritable = __arraySize(writableResultFdArray);
+ }
+ if (exceptionResultFdArray != nil) {
+ if (! __isArrayLike(exceptionResultFdArray)) {
+ goto fail;
+ }
+ resultSizeException = __arraySize(exceptionResultFdArray);
+ }
+
+ 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;
+ }
+ __resultR = __arrayVal(readableResultFdArray);
+ __resultW = __arrayVal(writableResultFdArray);
+ __resultE = __arrayVal(exceptionResultFdArray);
+
+ for (i = 0; (i < readCount) && (numHandles < MAXHANDLE); i++) {
+ fd = __arrayVal(readFdArray)[i];
+
+ if (fd != nil) {
+ if (__isExternalAddressLike(fd)) {
+ hArray [numHandles] = _HANDLEVal(fd);
+ retArray[numHandles] = i;
+ ++numHandles;
+ } else {
+ int canRead = _canReadWithoutBlocking (__intVal(fd) );
+
+ if (canRead > 0 ) {
+ if (cntR < resultSizeReadable) {
+ __resultR[cntR] = fd;
+ }
+ cntR++;
+ } else {
+ if (canRead < 0 ) {
+ @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+ RETURN (__mkSmallInteger(-1));
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0; (i < writeCount) && (numHandles < MAXHANDLE);i++) {
+ fd = __arrayVal(writeFdArray)[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 ) {
+ if (cntW < resultSizeWritable) {
+ __resultW[cntW] = fd;
+ }
+ cntW++;
+ } else {
+ if (canWrite < 0 ) {
+ @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+ RETURN (__mkSmallInteger(-1));
+ }
+ }
+ }
+ }
+ }
+
+ for (i = 0; (i < exceptCount) && (numHandles < MAXHANDLE);i++) {
+ fd = __arrayVal(exceptFdArray)[i];
+
+ if (fd != nil) {
+ if (__isExternalAddressLike(fd)) {
+ hArray [numHandles] = _HANDLEVal(fd);
+ retArray[numHandles] = i + 20000;
+ ++numHandles;
+ }
+ }
+ }
+
+ if (cntR || cntW) {
+ // for now: we are done
+ RETURN(__mkSmallInteger(cntR+cntW+cntE));
+ // maybe later: check for other handles immediately
+ t = 0;
+ } else {
+ if (__isSmallInteger(millis)) {
+ t = __intVal(millis);
+
+ if (t <= 0 && numHandles == 0) {
+ RETURN (__mkSmallInteger(0));
+ }
+ } else {
+ t = INFINITE;
+ }
+ }
+
+#ifdef SELECT3DEBUGWIN32
+ console_printf("wait Handles = %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 (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) {
+ 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;
+
+#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++;
+ }
+ if (fd < 20000) {
+ if (cntW < resultSizeWritable) {
+ OBJ temp = __arrayVal(writeFdArray)[fd-10000];
+ __resultW[cntW] = temp;
+ __STORE(writableResultFdArray, temp);
+ }
+ cntW++;
+ }
+ if (cntE < resultSizeException) {
+ OBJ temp = __arrayVal(exceptFdArray)[fd-20000];
+ __resultE[cntE] = temp;
+ __STORE(exceptionResultFdArray, temp);
+ }
+ cntE++;
+ }
+ 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
+ goto done;
+ }
+
+polling:
+ for (i=0; i < readCount; i++) {
+ fd = __arrayVal(readFdArray)[i];
+ if (fd != nil && ! __isExternalAddressLike(fd)) {
+ int canRead = _canReadWithoutBlocking (__intVal(fd));
+
+ if (canRead > 0 ) {
+ if (cntR < resultSizeReadable) {
+ __resultR[cntR] = fd;
+ }
+ cntR++;
+ } else {
+ if (canRead < 0 ) {
+ @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+ RETURN (__mkSmallInteger(-1));
+ }
+ }
+ }
+ }
+
+ for (i=0; i < writeCount;i++) {
+ fd = __arrayVal(writeFdArray)[i];
+ if (fd != nil && ! __isExternalAddressLike(fd)) {
+ int canWrite = _canWriteWithoutBlocking (__intVal(fd));
+
+ if (canWrite > 0 ) {
+ if (cntW < resultSizeWritable) {
+ __resultW[cntW] = __mkSmallInteger(i);
+ }
+ cntW++;
+ } else {
+ if (canWrite < 0 ) {
+ @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+ RETURN (__mkSmallInteger(-1));
+ }
+ }
+ }
+ }
+
+done:
+ /* add a delimiter */
+ if (cntR < resultSizeReadable) {
+ __resultR[cntR] = nil;
+ }
+ if (cntW < resultSizeWritable) {
+ __resultW[cntW] = nil;
+ }
+ if (cntE < resultSizeException) {
+ __resultE[cntE] = 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
@@ -17548,15 +17857,15 @@
!Win32OperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.494 2014-04-04 08:24:43 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.494 2014-04-04 08:24:43 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
!
version_SVN
- ^ '$Id: Win32OperatingSystem.st,v 1.494 2014-04-04 08:24:43 stefan Exp $'
+ ^ '$Id: Win32OperatingSystem.st,v 1.495 2014-04-10 08:54:27 stefan Exp $'
! !