UnixOperatingSystem.st
changeset 7494 2dd5a54c22ed
parent 7465 1b616e80d565
child 7500 e4fbe86c7341
--- a/UnixOperatingSystem.st	Fri Jul 11 19:52:44 2003 +0200
+++ b/UnixOperatingSystem.st	Fri Jul 11 19:53:47 2003 +0200
@@ -9645,6 +9645,211 @@
     ^ super readCheck:fd
 !
 
+selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray 
+        into:resultFdArray 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 filedescriptors which are ready are returned in resultArray.
+
+     Return the number of selected filedescriptors"
+
+%{
+    fd_set rset, wset, eset;
+    struct timeval wt, et;
+    int f, maxF, i, lX, bX;
+    INT t;
+    OBJ fd, retFd;
+    int ret;
+    int count, resultCount;
+    int numFds = 0;
+#ifndef __isArrayLike
+# define __isArrayLike __isArray
+#endif
+
+    if (!__isSmallInteger(millis)) {
+        goto fail;
+    }
+    if (! __isArrayLike(resultFdArray)) {
+        goto fail;    
+    }
+    resultCount = __arraySize(resultFdArray);
+
+    FD_ZERO(&rset);
+    FD_ZERO(&wset);
+    FD_ZERO(&eset);
+
+    maxF = -1;
+    if (__isNonNilObject(readFdArray)) {
+        if (! __isArrayLike(readFdArray)) {
+            goto fail;    
+        }
+        count = __arraySize(readFdArray);
+
+        for (i=0; i<count;i++) {
+            fd = __ArrayInstPtr(readFdArray)->a_element[i];
+            if (fd != nil) {
+                if (! __isSmallInteger(fd)) {
+                    if (@global(InfoPrinting) == true) {
+                        fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd);
+                    }
+                } else {
+                    f = __intVal(fd);
+                    if ((unsigned)f < FD_SETSIZE) {
+                        FD_SET(f, &rset);
+                        if (f > maxF) maxF = f;
+                        numFds++;
+                    } else {
+                        if (@global(InfoPrinting) == true) {
+                            fprintf(stderr, "[OS] warning: huge read-fd (0x%x) given to select\n", fd);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (__isNonNilObject(writeFdArray)) {
+        if (! __isArrayLike(writeFdArray)) {
+            goto fail;    
+        }
+        count = __arraySize(writeFdArray);
+        for (i=0; i<count;i++) {
+            fd = __ArrayInstPtr(writeFdArray)->a_element[i];
+            if (fd != nil) {
+                if (! __isSmallInteger(fd)) {
+                    if (@global(InfoPrinting) == true) {
+                        fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd);
+                    }
+                } else {
+                    f = __intVal(fd);
+                    if ((unsigned)f < FD_SETSIZE) {
+                        FD_SET(f, &wset);       
+                        if (f > maxF) maxF = f;
+                        numFds++;
+                    } else {
+                        if (@global(InfoPrinting) == true) {
+                            fprintf(stderr, "[OS] warning: huge write-fd (0x%x) given to select\n", fd);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (__isNonNilObject(exceptFdArray)) {
+        if (! __isArrayLike(exceptFdArray)) {
+            goto fail;    
+        }
+        count = __arraySize(exceptFdArray);
+        for (i=0; i<count;i++) {
+            fd = __ArrayInstPtr(exceptFdArray)->a_element[i];
+            if (fd != nil) {
+                if (! __isSmallInteger(fd)) {
+                    if (@global(InfoPrinting) == true) {
+                        fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd);
+                    }
+                } else {
+                    f = __intVal(fd);
+                    if ((unsigned)f < FD_SETSIZE) {
+                        FD_SET(f, &eset);       
+                        if (f > maxF) maxF = f;
+                        numFds++;
+                    } else {
+                        if (@global(InfoPrinting) == true) {
+                            fprintf(stderr, "[OS] warning: huge except-fd (0x%x) given to select\n", fd);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    t = __intVal(millis);
+    if (t) {
+        wt.tv_sec = t / 1000;
+        wt.tv_usec = (t % 1000) * 1000;
+    } else {
+        wt.tv_sec = wt.tv_usec = 0;
+    }
+
+    /*
+     * make certain, that interrupt gets us out of the select
+     * However, we must then care for moved objects.
+     */
+    __BEGIN_INTERRUPTABLE__
+    errno = 0;
+
+    if (t == 0) {
+        /* 
+         * if there is no timeout time, we can stay here interruptable.
+         */
+        do {
+            ret = select(maxF+1, &rset, &wset, &eset, &wt);
+        } while ((ret < 0) && (errno == EINTR));
+    } else {
+        do {
+            ret = select(maxF+1, &rset, &wset, &eset, &wt);
+            /* 
+             * for now: dont loop; if we did, we had to adjust the vt-timeval;
+             * could otherwise stay in this loop forever ...
+             * Premature ret (before the time expired) must be handled by the caller.
+             * A good solution is to update the wt-timeval and redo the select.
+             */
+        } while (0 /* (ret < 0) && (errno == EINTR) */ );
+    }
+    __END_INTERRUPTABLE__
+
+    if (ret > 0) {
+        int cnt = 0;
+        OBJ *__result = __arrayVal(resultFdArray);
+
+        for (i=0; i <= maxF; i++) {
+            if (FD_ISSET(i, &rset)
+             || FD_ISSET(i, &wset)
+             || FD_ISSET(i, &eset)) {
+                if (cnt < resultCount) {
+                    __result[cnt] = __MKSMALLINT(i);
+                }
+                cnt++;
+            }
+        }
+        RETURN (__MKSMALLINT(cnt));
+    } else {
+        if (ret < 0) {
+            if (errno == EINTR) {
+                errno = 0;
+                @global(LastErrorNumber) = nil;
+            } else {
+                if (@global(InfoPrinting) == true) {
+                    fprintf(stderr, "OS [info]: select errno = %d\n", errno);
+                }
+                @global(LastErrorNumber) = __MKSMALLINT(errno);
+            }
+        } else {
+            @global(LastErrorNumber) = nil;
+        }
+    }
+
+    /*
+     * Return 0 (no filedescriptor ready)
+     */
+    RETURN (__MKSMALLINT(0));
+
+
+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 
@@ -13347,7 +13552,7 @@
 !UnixOperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.171 2003-07-01 11:15:10 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/UnixOperatingSystem.st,v 1.172 2003-07-11 17:53:47 stefan Exp $'
 ! !
 
 UnixOperatingSystem initialize!