"Fossies" - the Fresh Open Source Software Archive

Member "seed7/src/pol_sel.c" (17 Dec 2019, 49114 Bytes) of package /linux/misc/seed7_05_20210223.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pol_sel.c" see the Fossies "Dox" file reference documentation.

    1 /********************************************************************/
    2 /*                                                                  */
    3 /*  pol_sel.c     Poll type and function based on select function.  */
    4 /*  Copyright (C) 1989 - 2013  Thomas Mertes                        */
    5 /*                                                                  */
    6 /*  This file is part of the Seed7 Runtime Library.                 */
    7 /*                                                                  */
    8 /*  The Seed7 Runtime Library is free software; you can             */
    9 /*  redistribute it and/or modify it under the terms of the GNU     */
   10 /*  Lesser General Public License as published by the Free Software */
   11 /*  Foundation; either version 2.1 of the License, or (at your      */
   12 /*  option) any later version.                                      */
   13 /*                                                                  */
   14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
   15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
   16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
   17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
   18 /*  details.                                                        */
   19 /*                                                                  */
   20 /*  You should have received a copy of the GNU Lesser General       */
   21 /*  Public License along with this program; if not, write to the    */
   22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
   23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
   24 /*                                                                  */
   25 /*  Module: Seed7 Runtime Library                                   */
   26 /*  File: seed7/src/pol_sel.c                                       */
   27 /*  Changes: 2011, 2013  Thomas Mertes                              */
   28 /*  Content: Poll type and function based on select function.       */
   29 /*                                                                  */
   30 /********************************************************************/
   31 
   32 #define LOG_FUNCTIONS 0
   33 #define VERBOSE_EXCEPTIONS 0
   34 
   35 #include "version.h"
   36 
   37 #include "stdlib.h"
   38 #include "stdio.h"
   39 #include "string.h"
   40 #if SOCKET_LIB == WINSOCK_SOCKETS
   41 #define FD_SETSIZE 65536
   42 #include "winsock2.h"
   43 #else
   44 #include "sys/select.h"
   45 #endif
   46 #include "errno.h"
   47 
   48 #include "common.h"
   49 #include "data_rtl.h"
   50 #include "heaputl.h"
   51 #include "hsh_rtl.h"
   52 #include "soc_rtl.h"
   53 #include "rtl_err.h"
   54 
   55 #undef EXTERN
   56 #define EXTERN
   57 #include "pol_drv.h"
   58 
   59 
   60 #if SOCKET_LIB == UNIX_SOCKETS
   61 
   62 #define DYNAMIC_FD_SET 0
   63 #define SELECT_WITH_NFDS 1
   64 #define VERIFY_FD_SETSIZE 0
   65 #define VERIFY_MAXIMUM_FD_NUMBER 1
   66 #define SIZEOF_FD_SET(size) sizeof(fd_set)
   67 #define USED_FD_SET_SIZE(fdset) sizeof(fd_set)
   68 
   69 #elif SOCKET_LIB == WINSOCK_SOCKETS
   70 
   71 #define DYNAMIC_FD_SET 1
   72 #define SELECT_WITH_NFDS 0
   73 #define VERIFY_FD_SETSIZE 1
   74 #define VERIFY_MAXIMUM_FD_NUMBER 0
   75 #define SIZEOF_FD_SET(size) \
   76     (sizeof(fd_set) - FD_SETSIZE * sizeof(SOCKET) + (size) * sizeof(SOCKET))
   77 #define USED_FD_SET_SIZE(fdset) SIZEOF_FD_SET((fdset)->fd_count)
   78 
   79 #endif
   80 
   81 #define USE_PREPARED_FD_SET 1
   82 #define MEMCPY_FD_SET 1
   83 
   84 
   85 typedef enum {
   86     ITER_EMPTY,
   87     ITER_CHECKS_IN, ITER_CHECKS_OUT, ITER_CHECKS_INOUT,
   88     ITER_FINDINGS_IN, ITER_FINDINGS_OUT, ITER_FINDINGS_INOUT
   89   } iteratorType;
   90 
   91 typedef struct {
   92     os_socketType fd;
   93     genericType file;
   94   } fdAndFileType;
   95 
   96 typedef struct {
   97 #if DYNAMIC_FD_SET
   98 #if USE_PREPARED_FD_SET
   99     fd_set *inFdset;
  100 #endif
  101     fd_set *outFdset;
  102 #else
  103 #if USE_PREPARED_FD_SET
  104     fd_set inFdset;
  105 #endif
  106     fd_set outFdset;
  107 #endif
  108 #if USE_PREPARED_FD_SET && SELECT_WITH_NFDS
  109     int preparedNfds;
  110 #endif
  111     memSizeType size;
  112     memSizeType capacity;
  113     memSizeType iterPos;
  114     fdAndFileType *files;
  115     rtlHashType indexHash;
  116   } testType;
  117 
  118 typedef struct {
  119     testType readTest;
  120     testType writeTest;
  121     iteratorType iteratorMode;
  122     memSizeType iterEvents;
  123     memSizeType numOfEvents;
  124   } select_based_pollRecord, *select_based_pollType;
  125 
  126 typedef const select_based_pollRecord *const_select_based_pollType;
  127 
  128 #if DO_HEAP_STATISTIC
  129 size_t sizeof_pollRecord = sizeof(select_based_pollRecord);
  130 #endif
  131 
  132 #define conv(genericPollData) ((const_select_based_pollType) genericPollData)
  133 #define var_conv(genericPollData) ((select_based_pollType) genericPollData)
  134 
  135 
  136 #if DYNAMIC_FD_SET
  137 
  138 #define to_inFdset(test)            ((test)->inFdset)
  139 #define to_outFdset(test)           ((test)->outFdset)
  140 #define to_read_inFdset(data)       (((const_select_based_pollType) data)->readTest.inFdset)
  141 #define to_write_inFdset(data)      (((const_select_based_pollType) data)->writeTest.inFdset)
  142 #define to_read_outFdset(data)      (((const_select_based_pollType) data)->readTest.outFdset)
  143 #define to_write_outFdset(data)     (((const_select_based_pollType) data)->writeTest.outFdset)
  144 #define to_var_read_inFdset(data)   (((select_based_pollType) data)->readTest.inFdset)
  145 #define to_var_write_inFdset(data)  (((select_based_pollType) data)->writeTest.inFdset)
  146 #define to_var_read_outFdset(data)  (((select_based_pollType) data)->readTest.outFdset)
  147 #define to_var_write_outFdset(data) (((select_based_pollType) data)->writeTest.outFdset)
  148 
  149 #define ALLOC_FDSET(var,nr)      (ALLOC_HEAP(var, fd_set *, SIZEOF_FD_SET(nr))?CNT(CNT1_BYT(SIZEOF_FD_SET(nr))) TRUE:FALSE)
  150 #define FREE_FDSET(var,nr)       (CNT(CNT2_BYT(SIZEOF_FD_SET(nr))) FREE_HEAP(var, SIZEOF_FD_SET(nr)))
  151 #define REALLOC_FDSET(var,nr)    REALLOC_HEAP(var, fd_set *, SIZEOF_FD_SET(nr))
  152 #define COUNT3_FDSET(nr1,nr2)    CNT3(CNT2_BYT(SIZEOF_FD_SET(nr1)), CNT1_BYT(SIZEOF_FD_SET(nr2)))
  153 
  154 #else
  155 
  156 #define to_inFdset(test)            (&(test)->inFdset)
  157 #define to_outFdset(test)           (&(test)->outFdset)
  158 #define to_read_inFdset(data)       (&((const_select_based_pollType) data)->readTest.inFdset)
  159 #define to_write_inFdset(data)      (&((const_select_based_pollType) data)->writeTest.inFdset)
  160 #define to_read_outFdset(data)      (&((const_select_based_pollType) data)->readTest.outFdset)
  161 #define to_write_outFdset(data)     (&((const_select_based_pollType) data)->writeTest.outFdset)
  162 #define to_var_read_inFdset(data)   (&((select_based_pollType) data)->readTest.inFdset)
  163 #define to_var_write_inFdset(data)  (&((select_based_pollType) data)->writeTest.inFdset)
  164 #define to_var_read_outFdset(data)  (&((select_based_pollType) data)->readTest.outFdset)
  165 #define to_var_write_outFdset(data) (&((select_based_pollType) data)->writeTest.outFdset)
  166 
  167 #endif
  168 
  169 
  170 #define TABLE_START_SIZE  256
  171 #define TABLE_INCREMENT  1024
  172 
  173 
  174 
  175 #ifdef OUT_OF_ORDER
  176 static void dumpPoll (const const_pollType pollData)
  177     {
  178       memSizeType pos;
  179 /*
  180       printf("readSize=%d\n", conv(pollData)->readTest.size);
  181       printf("readCapacity=%d\n", conv(pollData)->readTest.capacity);
  182       printf("readPos=%d\n", conv(pollData)->readTest.pos);
  183       printf("writeSize=%d\n", conv(pollData)->writeTest.size);
  184       printf("writeCapacity=%d\n", conv(pollData)->writeTest.capacity);
  185       printf("writePos=%d\n", conv(pollData)->writeTest.pos);
  186       printf("iteratorMode=%d\n", conv(pollData)->iteratorMode);
  187       printf("iterEvents=%d\n", conv(pollData)->iterEvents);
  188       printf("numOfEvents=%d\n", conv(pollData)->numOfEvents);
  189       */
  190 #if USE_PREPARED_FD_SET
  191       //if (conv(pollData)->readTest.size <= 5) {
  192       printf("readFds:");
  193       for (pos = 0; pos < conv(pollData)->readTest.size; pos++) {
  194         printf(" %d", conv(pollData)->readTest.files[pos].fd);
  195         if (!FD_ISSET(conv(pollData)->readTest.files[pos].fd, to_read_inFdset(pollData))) {
  196           printf("*");
  197         }
  198       }
  199       printf("\n");
  200       //}
  201       /*
  202       printf("writeFds:");
  203       for (pos = 0; pos < conv(pollData)->writeTest.size; pos++) {
  204         printf(" %d", conv(pollData)->writeTest.files[pos].fd);
  205         if (!FD_ISSET(conv(pollData)->writeTest.files[pos].fd, to_write_inFdset(pollData))) {
  206           printf("*");
  207         }
  208       }
  209       */
  210 #endif
  211     }
  212 #endif
  213 
  214 
  215 
  216 void initPollOperations (const createFuncType incrUsageCount,
  217     const destrFuncType decrUsageCount)
  218 
  219   { /* initPollOperations */
  220     fileObjectOps.incrUsageCount = incrUsageCount;
  221     fileObjectOps.decrUsageCount = decrUsageCount;
  222   } /* initPollOperations */
  223 
  224 
  225 
  226 #if MEMCPY_FD_SET
  227 #define copyFdSet(dest, source, unused) memcpy(dest, source, USED_FD_SET_SIZE(source))
  228 #else
  229 
  230 static void copyFdSet (fd_set *dest, const fd_set *source, testType *test)
  231 
  232   {
  233     memSizeType pos;
  234 
  235   /* copyFdSet */
  236     FD_ZERO(dest);
  237     for (pos = 0; pos < test->size; pos++) {
  238       if (FD_ISSET(test->files[pos].fd, source)) {
  239         FD_SET(test->files[pos].fd, dest);
  240       } /* if */
  241     } /* for */
  242   } /* copyFdSet */
  243 #endif
  244 
  245 
  246 
  247 #if !DYNAMIC_FD_SET
  248 #define allocFdSet(test, capacity) TRUE
  249 #else
  250 
  251 static boolType allocFdSet (testType *test, memSizeType capacity)
  252 
  253   {
  254     boolType result = TRUE;
  255 
  256   /* allocFdSet */
  257 #if USE_PREPARED_FD_SET
  258     if (unlikely(!ALLOC_FDSET(test->inFdset, capacity))) {
  259       result = FALSE;
  260       test->outFdset = NULL;
  261     } else if (unlikely(!ALLOC_FDSET(test->outFdset, capacity))) {
  262       result = FALSE;
  263       FREE_FDSET(test->inFdset, capacity);
  264       test->inFdset = NULL;
  265     } /* if */
  266 #else
  267     if (unlikely(!ALLOC_FDSET(test->outFdset, capacity))) {
  268       result = FALSE;
  269     } /* if */
  270 #endif
  271     return result;
  272   } /* allocFdSet */
  273 #endif
  274 
  275 
  276 
  277 #if !DYNAMIC_FD_SET
  278 #define freeFdSet(test, capacity) 0
  279 #else
  280 
  281 static void freeFdSet (testType *test, memSizeType capacity)
  282 
  283   { /* freeFdSet */
  284     if (test->outFdset != NULL) {
  285 #if USE_PREPARED_FD_SET
  286       FREE_FDSET(test->inFdset, capacity);
  287 #endif
  288       FREE_FDSET(test->outFdset, capacity);
  289     } /* if */
  290   } /* freeFdSet */
  291 #endif
  292 
  293 
  294 
  295 #if !DYNAMIC_FD_SET
  296 #define reallocFdSet(pollData, increment) TRUE
  297 #else
  298 
  299 static boolType reallocFdSet (testType *test, memSizeType increment)
  300 
  301   {
  302     fd_set *newFdset;
  303     boolType result = TRUE;
  304 
  305   /* reallocFdSet */
  306 #if USE_PREPARED_FD_SET
  307     if (unlikely((newFdset = REALLOC_FDSET(test->inFdset,
  308         test->capacity + increment)) == NULL)) {
  309       result = FALSE;
  310     } else {
  311       COUNT3_FDSET(test->capacity,
  312                    test->capacity + increment);
  313       test->inFdset = newFdset;
  314     } /* if */
  315 #endif
  316     if (unlikely((newFdset = REALLOC_FDSET(test->outFdset,
  317         test->capacity + increment)) == NULL)) {
  318       result = FALSE;
  319     } else {
  320       COUNT3_FDSET(test->capacity,
  321                    test->capacity + increment);
  322       test->outFdset = newFdset;
  323     } /* if */
  324     return result;
  325   } /* reallocFdSet */
  326 #endif
  327 
  328 
  329 
  330 #if !DYNAMIC_FD_SET
  331 #define replaceFdSet(test, capacity) TRUE
  332 #else
  333 
  334 static boolType replaceFdSet (testType *test, memSizeType capacity)
  335 
  336   {
  337 #if USE_PREPARED_FD_SET
  338     fd_set *newInFdset;
  339 #endif
  340     fd_set *newOutFdset;
  341     boolType result = TRUE;
  342 
  343   /* replaceFdSet */
  344 #if USE_PREPARED_FD_SET
  345     if (unlikely(!ALLOC_FDSET(newInFdset, capacity))) {
  346       result = FALSE;
  347     } /* if */
  348 #endif
  349     if (unlikely(!ALLOC_FDSET(newOutFdset, capacity))) {
  350       result = FALSE;
  351 #if USE_PREPARED_FD_SET
  352       if (newInFdset != NULL) {
  353         FREE_FDSET(newInFdset, capacity);
  354       } /* if */
  355 #endif
  356     } /* if */
  357     if (result) {
  358 #if USE_PREPARED_FD_SET
  359       FREE_FDSET(test->inFdset, capacity);
  360       test->inFdset = newInFdset;
  361 #endif
  362       FREE_FDSET(test->outFdset, capacity);
  363       test->outFdset = newOutFdset;
  364     } /* if */
  365     return result;
  366   } /* replaceFdSet */
  367 #endif
  368 
  369 
  370 
  371 static void addCheck (testType *test, const socketType aSocket,
  372     const genericType fileObj)
  373 
  374   {
  375     memSizeType pos;
  376 
  377   /* addCheck */
  378     /* printf("addCheck(..., %u, 0x%lx)\n", aSocket, (unsigned long) fileObj); */
  379 #if VERIFY_MAXIMUM_FD_NUMBER
  380     if (aSocket < 0 || aSocket >= FD_SETSIZE) {
  381       raise_error(FILE_ERROR);
  382       return;
  383     } /* if */
  384 #endif
  385 #if VERIFY_FD_SETSIZE
  386     if (test->size >= FD_SETSIZE) {
  387       raise_error(FILE_ERROR);
  388       return;
  389     } /* if */
  390 #endif
  391     pos = (memSizeType) hshIdxEnterDefault(test->indexHash,
  392         (genericType) (usocketType) aSocket, (genericType) test->size,
  393         (intType) aSocket);
  394     if (pos == test->size) {
  395       if (test->size >= test->capacity) {
  396         test->files = REALLOC_TABLE(test->files,
  397             fdAndFileType, test->capacity,
  398             test->capacity + TABLE_INCREMENT);
  399         if (test->files == NULL ||
  400             !reallocFdSet(test, TABLE_INCREMENT)) {
  401           raise_error(MEMORY_ERROR);
  402           return;
  403         } else {
  404           COUNT3_TABLE(fdAndFileType, test->capacity,
  405                        test->capacity + TABLE_INCREMENT);
  406           test->capacity += TABLE_INCREMENT;
  407           /* printf("increment table to %lu\n", test->capacity); */
  408         } /* if */
  409       } /* if */
  410       test->size++;
  411       test->files[pos].fd = (os_socketType) aSocket;
  412       test->files[pos].file = fileObjectOps.incrUsageCount(fileObj);
  413 #if USE_PREPARED_FD_SET
  414       FD_SET((os_socketType) aSocket, to_inFdset(test));
  415 #if SELECT_WITH_NFDS
  416       if (aSocket >= test->preparedNfds) {
  417         test->preparedNfds = (int) aSocket + 1;
  418       } /* if */
  419 #endif
  420 #endif
  421     } /* if */
  422   } /* addCheck */
  423 
  424 
  425 
  426 static void removeCheck (testType *test, const socketType aSocket)
  427 
  428   {
  429     memSizeType pos;
  430 
  431   /* removeCheck */
  432     /* printf("removeCheck(..., %u)\n", aSocket); */
  433     pos = (memSizeType) hshIdxWithDefault(test->indexHash,
  434         (genericType) (usocketType) aSocket, (genericType) test->size,
  435         (intType) aSocket, (compareType) &genericCmp);
  436     if (pos != test->size) {
  437       fileObjectOps.decrUsageCount(test->files[pos].file);
  438       if (pos + 1 <= test->iterPos) {
  439         test->iterPos--;
  440         if (pos < test->iterPos) {
  441           memcpy(&test->files[pos],
  442                  &test->files[test->iterPos], sizeof(fdAndFileType));
  443           hshIdxAddr(test->indexHash,
  444                      (genericType) (usocketType) test->files[pos].fd,
  445                      (intType) (socketType) test->files[pos].fd,
  446                      (compareType) &genericCmp)->value.genericValue = (genericType) pos;
  447           pos = test->iterPos;
  448         } /* if */
  449       } /* if */
  450       test->size--;
  451       if (pos < test->size) {
  452         memcpy(&test->files[pos],
  453                &test->files[test->size], sizeof(fdAndFileType));
  454         hshIdxAddr(test->indexHash,
  455                    (genericType) (usocketType) test->files[pos].fd,
  456                    (intType) (socketType) test->files[pos].fd,
  457                    (compareType) &genericCmp)->value.genericValue = (genericType) pos;
  458       } /* if */
  459       hshExcl(test->indexHash, (genericType) (usocketType) aSocket,
  460               (intType) aSocket, (compareType) &genericCmp,
  461               (destrFuncType) &genericDestr, (destrFuncType) &genericDestr);
  462 #if USE_PREPARED_FD_SET
  463       FD_CLR((os_socketType) aSocket, to_inFdset(test));
  464 #endif
  465     } /* if */
  466   } /* removeCheck */
  467 
  468 
  469 
  470 static void doPoll (const pollType pollData, struct timeval *timeout)
  471 
  472   {
  473     int nfds = 0;
  474     fd_set *readFds;
  475     fd_set *writeFds;
  476 #if !USE_PREPARED_FD_SET
  477     memSizeType pos;
  478     os_socketType sock;
  479 #endif
  480     int select_result;
  481 
  482   /* doPoll */
  483     /* printf("doPoll\n");
  484        dumpPoll(pollData); */
  485     readFds = to_var_read_outFdset(pollData);
  486 #if USE_PREPARED_FD_SET
  487     copyFdSet(readFds, to_read_inFdset(pollData),
  488               &conv(pollData)->readTest.files);
  489 #if SELECT_WITH_NFDS
  490     nfds = conv(pollData)->readTest.preparedNfds;
  491 #endif
  492 #else
  493     FD_ZERO(readFds);
  494     for (pos = 0; pos < conv(pollData)->readTest.size; pos++) {
  495       sock = conv(pollData)->readTest.files[pos].fd;
  496       FD_SET(sock, readFds);
  497 #if SELECT_WITH_NFDS
  498       if ((int) sock >= nfds) {
  499         nfds = (int) sock + 1;
  500       } /* if */
  501 #endif
  502     } /* for */
  503 #endif
  504     writeFds = to_var_write_outFdset(pollData);
  505 #if USE_PREPARED_FD_SET
  506     copyFdSet(writeFds, to_write_inFdset(pollData),
  507               &conv(pollData)->writeTest.files);
  508 #if SELECT_WITH_NFDS
  509     if (conv(pollData)->writeTest.preparedNfds > nfds) {
  510       nfds = conv(pollData)->writeTest.preparedNfds;
  511     } /* if */
  512 #endif
  513 #else
  514     FD_ZERO(writeFds);
  515     for (pos = 0; pos < conv(pollData)->writeTest.size; pos++) {
  516       sock = conv(pollData)->writeTest.files[pos].fd;
  517       FD_SET(sock, writeFds);
  518 #if SELECT_WITH_NFDS
  519       if ((int) sock >= nfds) {
  520         nfds = (int) sock + 1;
  521       } /* if */
  522 #endif
  523     } /* for */
  524 #endif
  525     /* printf("doPoll %lx: nfds=%d\n", pollData, nfds); */
  526     do {
  527       select_result = select(nfds, readFds, writeFds, NULL, timeout);
  528     } while (unlikely(select_result == -1 && errno == EINTR));
  529     if (unlikely(select_result < 0)) {
  530       logError(printf("doPoll: select(%d, *, *, NULL, " FMT_U_MEM ") failed:\n"
  531                       "%s=%d\nerror: %s\n",
  532                       nfds, (memSizeType) timeout, ERROR_INFORMATION););
  533       raise_error(FILE_ERROR);
  534     } else {
  535       var_conv(pollData)->readTest.iterPos = 0;
  536       var_conv(pollData)->writeTest.iterPos = 0;
  537       var_conv(pollData)->numOfEvents = (memSizeType) select_result;
  538     } /* if */
  539   } /* doPoll */
  540 
  541 
  542 
  543 static boolType isChecked (const testType *test, const socketType aSocket)
  544 
  545   {
  546     memSizeType pos;
  547     boolType result;
  548 
  549   /* isChecked */
  550     pos = (memSizeType) hshIdxWithDefault(test->indexHash,
  551         (genericType) (usocketType) aSocket, (genericType) test->size,
  552         (intType) aSocket, (compareType) &genericCmp);
  553     result = pos != test->size;
  554     /* printf("isChecked: sock=%d, pos=%d, fd=%d\n",
  555         aSocket, pos, test->files[pos].fd); */
  556     return result;
  557   } /* isChecked */
  558 
  559 
  560 
  561 static boolType isReady (const testType *test, const socketType aSocket)
  562 
  563   {
  564     memSizeType pos;
  565     boolType result;
  566 
  567   /* isReady */
  568     pos = (memSizeType) hshIdxWithDefault(test->indexHash,
  569         (genericType) (usocketType) aSocket, (genericType) test->size,
  570         (intType) aSocket, (compareType) &genericCmp);
  571     if (pos == test->size) {
  572       result = FALSE;
  573     } else {
  574       result = FD_ISSET(test->files[pos].fd, to_outFdset(test)) != 0;
  575       /* printf("isReady: sock=%d, pos=%d, fd=%d\n",
  576           aSocket, pos, test->files[pos].fd); */
  577     } /* if */
  578     return result;
  579   } /* isReady */
  580 
  581 
  582 
  583 static boolType hasNextCheck (const testType *test)
  584 
  585   { /* hasNextCheck */
  586     return test->iterPos < test->size;
  587   } /* hasNextCheck */
  588 
  589 
  590 
  591 static boolType hasNextFinding (testType *test, memSizeType iterEvents)
  592 
  593   {
  594     memSizeType pos;
  595     fd_set *fdSet;
  596     boolType hasNext;
  597 
  598   /* hasNextFinding */
  599     if (iterEvents == 0) {
  600       hasNext = FALSE;
  601       test->iterPos = test->size;
  602     } else {
  603       pos = test->iterPos;
  604       fdSet = to_outFdset(test);
  605       while (pos < test->size &&
  606           !FD_ISSET(test->files[pos].fd, fdSet)) {
  607         pos++;
  608       } /* while */
  609       hasNext = pos < test->size;
  610       test->iterPos = pos;
  611     } /* if */
  612     return hasNext;
  613   } /* hasNextFinding */
  614 
  615 
  616 
  617 static genericType nextCheck (testType *test,
  618     const genericType nullFile)
  619 
  620   {
  621     memSizeType pos;
  622     genericType checkFile;
  623 
  624   /* nextCheck */
  625     pos = test->iterPos;
  626     if (pos < test->size) {
  627       checkFile = test->files[pos].file;
  628       /* printf("nextCheck -> 0x%lx fd[%u]=%d\n",
  629           (unsigned long) checkFile, pos,
  630           test->files[pos].fd); */
  631       test->iterPos = pos + 1;
  632     } else {
  633       checkFile = nullFile;
  634     } /* if */
  635     return checkFile;
  636   } /* nextCheck */
  637 
  638 
  639 
  640 static genericType nextFinding (testType *test,
  641     memSizeType *iterEvents, const genericType nullFile)
  642 
  643   {
  644     memSizeType pos;
  645     fd_set *fdSet;
  646     genericType resultFile;
  647 
  648   /* nextFinding */
  649     if (*iterEvents == 0) {
  650       resultFile = nullFile;
  651       test->iterPos = test->size;
  652     } else {
  653       pos = test->iterPos;
  654       fdSet = to_outFdset(test);
  655       while (pos < test->size &&
  656           !FD_ISSET(test->files[pos].fd, fdSet)) {
  657         pos++;
  658       } /* while */
  659       if (pos < test->size) {
  660         resultFile = test->files[pos].file;
  661         /* printf("nextFinding -> 0x%lx fd[%u]=%d\n",
  662             (unsigned long) resultFile, pos,
  663             test->files[pos].fd); */
  664         (*iterEvents)--;
  665         pos++;
  666       } else {
  667         resultFile = nullFile;
  668       } /* if */
  669       test->iterPos = pos;
  670     } /* if */
  671     return resultFile;
  672   } /* nextFinding */
  673 
  674 
  675 
  676 /**
  677  *  Add 'eventsToCheck' for 'aSocket' to 'pollData'.
  678  *  'EventsToCheck' can have one of the following values:
  679  *  - POLLIN check if data can be read from the corresponding socket.
  680  *  - POLLOUT check if data can be written to the corresponding socket.
  681  *  - POLLINOUT check if data can be read or written (POLLIN or POLLOUT).
  682  *
  683  *  @param pollData Poll data to which the event checks are added.
  684  *  @param aSocket Socket for which the events should be checked.
  685  *  @param eventsToCheck Events to be added to the checkedEvents
  686  *         field of 'pollData'.
  687  *  @param fileObj File to be returned, if the iterator returns
  688  *         files in 'pollData'.
  689  *  @exception RANGE_ERROR Illegal value for 'eventsToCheck'.
  690  *  @exception MEMORY_ERROR An out of memory situation occurred.
  691  *  @exception FILE_ERROR A limit of the operating system was reached.
  692  */
  693 void polAddCheck (const pollType pollData, const socketType aSocket,
  694     intType eventsToCheck, const genericType fileObj)
  695 
  696   { /* polAddCheck */
  697     switch (castIntTypeForSwitch(eventsToCheck)) {
  698       case POLL_IN:
  699         addCheck(&var_conv(pollData)->readTest, aSocket, fileObj);
  700         break;
  701       case POLL_OUT:
  702         addCheck(&var_conv(pollData)->writeTest, aSocket, fileObj);
  703         break;
  704       case POLL_INOUT:
  705         addCheck(&var_conv(pollData)->readTest, aSocket, fileObj);
  706         addCheck(&var_conv(pollData)->writeTest, aSocket, fileObj);
  707         break;
  708       default:
  709         raise_error(RANGE_ERROR);
  710         break;
  711     } /* switch */
  712   } /* polAddCheck */
  713 
  714 
  715 
  716 /**
  717  *  Clears 'pollData'.
  718  *  All sockets and all events are removed from 'pollData' and
  719  *  the iterator is reset, such that polHasNext() returns FALSE.
  720  */
  721 void polClear (const pollType pollData)
  722 
  723   {
  724     memSizeType pos;
  725 
  726   /* polClear */
  727     /* printf("polClear\n"); */
  728 #if USE_PREPARED_FD_SET
  729     FD_ZERO(to_read_inFdset(pollData));
  730     FD_ZERO(to_write_inFdset(pollData));
  731 #if SELECT_WITH_NFDS
  732     var_conv(pollData)->readTest.preparedNfds = 0;
  733     var_conv(pollData)->writeTest.preparedNfds = 0;
  734 #endif
  735 #endif
  736     FD_ZERO(to_read_outFdset(pollData));
  737     FD_ZERO(to_write_outFdset(pollData));
  738     /* Clear readTest */
  739     for (pos = 0; pos < conv(pollData)->readTest.size; pos++) {
  740       fileObjectOps.decrUsageCount(conv(pollData)->readTest.files[pos].file);
  741     } /* for */
  742     var_conv(pollData)->readTest.size = 0;
  743     var_conv(pollData)->readTest.iterPos = 0;
  744     hshDestr(conv(pollData)->readTest.indexHash, (destrFuncType) &genericDestr,
  745              (destrFuncType) &genericDestr);
  746     var_conv(pollData)->readTest.indexHash = hshEmpty();
  747     /* Clear writeTest */
  748     for (pos = 0; pos < conv(pollData)->readTest.size; pos++) {
  749       fileObjectOps.decrUsageCount(conv(pollData)->readTest.files[pos].file);
  750     } /* for */
  751     var_conv(pollData)->writeTest.size = 0;
  752     var_conv(pollData)->writeTest.iterPos = 0;
  753     hshDestr(conv(pollData)->writeTest.indexHash, (destrFuncType) &genericDestr,
  754              (destrFuncType) &genericDestr);
  755     var_conv(pollData)->writeTest.indexHash = hshEmpty();
  756     var_conv(pollData)->iteratorMode = ITER_EMPTY;
  757     var_conv(pollData)->iterEvents = 0;
  758     var_conv(pollData)->numOfEvents = 0;
  759   } /* polClear */
  760 
  761 
  762 
  763 /**
  764  *  Assign source to dest.
  765  *  A copy function assumes that dest contains a legal value.
  766  *  @exception MEMORY_ERROR Not enough memory to create dest.
  767  */
  768 void polCpy (const pollType dest, const const_pollType source)
  769 
  770   {
  771     select_based_pollType pollData;
  772     rtlHashType newReadIndexHash;
  773     rtlHashType newWriteIndexHash;
  774     memSizeType newReadFilesCapacity;
  775     fdAndFileType *newReadFiles;
  776     fdAndFileType *oldReadFiles;
  777     memSizeType oldReadFilesSize;
  778     memSizeType oldReadFilesCapacity;
  779     memSizeType newWriteFilesCapacity;
  780     fdAndFileType *newWriteFiles;
  781     fdAndFileType *oldWriteFiles;
  782     memSizeType oldWriteFilesSize;
  783     memSizeType oldWriteFilesCapacity;
  784     memSizeType pos;
  785 
  786   /* polCpy */
  787     logFunction(printf("polCpy(" FMT_U_MEM ", " FMT_U_MEM ")\n",
  788                        (memSizeType) dest, (memSizeType) source););
  789     if (dest != source) {
  790       newReadIndexHash = hshCreate(conv(source)->readTest.indexHash,
  791           (createFuncType) &genericCreate, (destrFuncType) &genericDestr,
  792           (createFuncType) &genericCreate, (destrFuncType) &genericDestr);
  793       newWriteIndexHash = hshCreate(conv(source)->writeTest.indexHash,
  794           (createFuncType) &genericCreate, (destrFuncType) &genericDestr,
  795           (createFuncType) &genericCreate, (destrFuncType) &genericDestr);
  796       if (unlikely(newReadIndexHash == NULL || newWriteIndexHash == NULL)) {
  797         raise_error(MEMORY_ERROR);
  798       } else {
  799         pollData = var_conv(dest);
  800         oldReadFiles = pollData->readTest.files;
  801         oldReadFilesSize = pollData->readTest.size;
  802         oldReadFilesCapacity = pollData->readTest.capacity;
  803         if (pollData->readTest.capacity < conv(source)->readTest.size) {
  804           newReadFilesCapacity = conv(source)->readTest.capacity;
  805         } else {
  806           newReadFilesCapacity = pollData->readTest.capacity;
  807         } /* if */
  808         if (unlikely(!ALLOC_TABLE(newReadFiles, fdAndFileType, newReadFilesCapacity))) {
  809           raise_error(MEMORY_ERROR);
  810           return;
  811         } else {
  812           if (pollData->readTest.capacity < conv(source)->readTest.size) {
  813             if (unlikely(!replaceFdSet(&pollData->readTest, conv(source)->readTest.capacity))) {
  814               FREE_TABLE(newReadFiles, fdAndFileType, newReadFilesCapacity);
  815               raise_error(MEMORY_ERROR);
  816               return;
  817             } else {
  818               pollData->readTest.capacity = conv(source)->readTest.capacity;
  819             } /* if */
  820           } /* if */
  821         } /* if */
  822         oldWriteFiles = pollData->writeTest.files;
  823         oldWriteFilesSize = pollData->writeTest.size;
  824         oldWriteFilesCapacity = pollData->writeTest.capacity;
  825         if (pollData->writeTest.capacity < conv(source)->writeTest.size) {
  826           newWriteFilesCapacity = conv(source)->writeTest.capacity;
  827         } else {
  828           newWriteFilesCapacity = pollData->writeTest.capacity;
  829         } /* if */
  830         if (unlikely(!ALLOC_TABLE(newWriteFiles, fdAndFileType, newWriteFilesCapacity))) {
  831           FREE_TABLE(newReadFiles, fdAndFileType, newReadFilesCapacity);
  832           raise_error(MEMORY_ERROR);
  833           return;
  834         } else {
  835           if (pollData->writeTest.capacity < conv(source)->writeTest.size) {
  836             if (unlikely(!replaceFdSet(&pollData->writeTest, conv(source)->writeTest.capacity))) {
  837               FREE_TABLE(newReadFiles, fdAndFileType, newReadFilesCapacity);
  838               FREE_TABLE(newWriteFiles, fdAndFileType, newWriteFilesCapacity);
  839               raise_error(MEMORY_ERROR);
  840               return;
  841             } else {
  842               pollData->writeTest.capacity = conv(source)->writeTest.capacity;
  843             } /* if */
  844           } /* if */
  845         } /* if */
  846 #if USE_PREPARED_FD_SET
  847         copyFdSet(to_var_read_inFdset(pollData), to_read_inFdset(source),
  848                   &conv(source)->readTest);
  849 #if SELECT_WITH_NFDS
  850         pollData->readTest.preparedNfds = conv(source)->readTest.preparedNfds;
  851 #endif
  852 #endif
  853         copyFdSet(to_var_read_outFdset(pollData), to_read_outFdset(source),
  854                   &conv(source)->readTest);
  855         pollData->readTest.size = conv(source)->readTest.size;
  856         pollData->readTest.files = newReadFiles;
  857         pollData->readTest.iterPos = conv(source)->readTest.iterPos;
  858         hshDestr(pollData->readTest.indexHash, (destrFuncType) &genericDestr,
  859                  (destrFuncType) &genericDestr);
  860         pollData->readTest.indexHash = newReadIndexHash;
  861 #if USE_PREPARED_FD_SET
  862         copyFdSet(to_var_write_inFdset(pollData), to_write_inFdset(source),
  863                   &conv(source)->writeTest);
  864 #if SELECT_WITH_NFDS
  865         pollData->writeTest.preparedNfds = conv(source)->writeTest.preparedNfds;
  866 #endif
  867 #endif
  868         copyFdSet(to_var_write_outFdset(pollData), to_write_outFdset(source),
  869                   &conv(source)->writeTest);
  870         pollData->writeTest.size = conv(source)->writeTest.size;
  871         pollData->writeTest.files = newWriteFiles;
  872         pollData->writeTest.iterPos = conv(source)->writeTest.iterPos;
  873         hshDestr(pollData->writeTest.indexHash, (destrFuncType) &genericDestr,
  874                  (destrFuncType) &genericDestr);
  875         pollData->writeTest.indexHash = newWriteIndexHash;
  876         pollData->iteratorMode = conv(source)->iteratorMode;
  877         pollData->iterEvents = conv(source)->iterEvents;
  878         pollData->numOfEvents = conv(source)->numOfEvents;
  879         for (pos = 0; pos < conv(source)->readTest.size; pos++) {
  880           newReadFiles[pos].fd = conv(source)->readTest.files[pos].fd;
  881           newReadFiles[pos].file =
  882               fileObjectOps.incrUsageCount(conv(source)->readTest.files[pos].file);
  883         } /* for */
  884         for (pos = 0; pos < conv(source)->writeTest.size; pos++) {
  885           newWriteFiles[pos].fd = conv(source)->writeTest.files[pos].fd;
  886           newWriteFiles[pos].file =
  887               fileObjectOps.incrUsageCount(conv(source)->writeTest.files[pos].file);
  888         } /* for */
  889         for (pos = 0; pos < oldReadFilesSize; pos++) {
  890           fileObjectOps.decrUsageCount(oldReadFiles[pos].file);
  891         } /* for */
  892         for (pos = 0; pos < oldWriteFilesSize; pos++) {
  893           fileObjectOps.decrUsageCount(oldWriteFiles[pos].file);
  894         } /* for */
  895         FREE_TABLE(oldReadFiles, fdAndFileType, oldReadFilesCapacity);
  896         FREE_TABLE(oldWriteFiles, fdAndFileType, oldWriteFilesCapacity);
  897       } /* if */
  898     } /* if */
  899     logFunction(printf("polCpy -->\n"););
  900     /* dumpPoll(dest); */
  901   } /* polCpy */
  902 
  903 
  904 
  905 /**
  906  *  Return a copy of source, that can be assigned to a new destination.
  907  *  It is assumed that the destination of the assignment is undefined.
  908  *  Create functions can be used to initialize Seed7 constants.
  909  *  @return a copy of source.
  910  *  @exception MEMORY_ERROR Not enough memory to represent the result.
  911  */
  912 pollType polCreate (const const_pollType source)
  913 
  914   {
  915     rtlHashType newReadIndexHash;
  916     rtlHashType newWriteIndexHash;
  917     memSizeType pos;
  918     select_based_pollType result;
  919 
  920   /* polCreate */
  921     logFunction(printf("polCreate(" FMT_U_MEM ")\n",
  922                        (memSizeType) source););
  923     newReadIndexHash = hshCreate(conv(source)->readTest.indexHash,
  924         (createFuncType) &genericCreate, (destrFuncType) &genericDestr,
  925         (createFuncType) &genericCreate, (destrFuncType) &genericDestr);
  926     newWriteIndexHash = hshCreate(conv(source)->writeTest.indexHash,
  927         (createFuncType) &genericCreate, (destrFuncType) &genericDestr,
  928         (createFuncType) &genericCreate, (destrFuncType) &genericDestr);
  929     if (unlikely(newReadIndexHash == NULL || newWriteIndexHash == NULL ||
  930                  !ALLOC_RECORD(result, select_based_pollRecord, count.polldata))) {
  931       raise_error(MEMORY_ERROR);
  932       result = NULL;
  933     } else {
  934       if (unlikely(!ALLOC_TABLE(result->readTest.files, fdAndFileType,
  935                                 conv(source)->readTest.capacity) ||
  936                    !ALLOC_TABLE(result->writeTest.files, fdAndFileType,
  937                                 conv(source)->writeTest.capacity) ||
  938                    !allocFdSet(&result->readTest, conv(source)->readTest.capacity) ||
  939                    !allocFdSet(&result->writeTest, conv(source)->writeTest.capacity))) {
  940         if (result->readTest.files != NULL) {
  941           FREE_TABLE(result->readTest.files, fdAndFileType, conv(source)->readTest.capacity);
  942           if (result->writeTest.files != NULL) {
  943             FREE_TABLE(result->writeTest.files, fdAndFileType, conv(source)->readTest.capacity);
  944             freeFdSet(&result->readTest, conv(source)->readTest.capacity);
  945           } /* if */
  946         } /* if */
  947         FREE_RECORD(result, select_based_pollRecord, count.polldata);
  948         raise_error(MEMORY_ERROR);
  949         result = NULL;
  950       } else {
  951 #if USE_PREPARED_FD_SET
  952         copyFdSet(to_var_read_inFdset(result), to_read_inFdset(source),
  953                   &conv(source)->readTest);
  954 #if SELECT_WITH_NFDS
  955         result->readTest.preparedNfds = conv(source)->readTest.preparedNfds;
  956 #endif
  957 #endif
  958         copyFdSet(to_var_read_outFdset(result), to_read_outFdset(source),
  959                   &conv(source)->readTest);
  960         result->readTest.size = conv(source)->readTest.size;
  961         result->readTest.capacity = conv(source)->readTest.capacity;
  962         result->readTest.iterPos = conv(source)->readTest.iterPos;
  963         for (pos = 0; pos < conv(source)->readTest.size; pos++) {
  964           result->readTest.files[pos].fd = conv(source)->readTest.files[pos].fd;
  965           result->readTest.files[pos].file =
  966               fileObjectOps.incrUsageCount(conv(source)->readTest.files[pos].file);
  967         } /* for */
  968         result->readTest.indexHash = newReadIndexHash;
  969 #if USE_PREPARED_FD_SET
  970         copyFdSet(to_var_write_inFdset(result), to_write_inFdset(source),
  971                   &conv(source)->writeTest);
  972 #if SELECT_WITH_NFDS
  973         result->writeTest.preparedNfds = conv(source)->writeTest.preparedNfds;
  974 #endif
  975 #endif
  976         copyFdSet(to_var_write_outFdset(result), to_write_outFdset(source),
  977                   &conv(source)->writeTest);
  978         result->writeTest.size = conv(source)->writeTest.size;
  979         result->writeTest.capacity = conv(source)->writeTest.capacity;
  980         result->writeTest.iterPos = conv(source)->writeTest.iterPos;
  981         for (pos = 0; pos < conv(source)->writeTest.size; pos++) {
  982           result->writeTest.files[pos].fd = conv(source)->writeTest.files[pos].fd;
  983           result->writeTest.files[pos].file =
  984               fileObjectOps.incrUsageCount(conv(source)->writeTest.files[pos].file);
  985         } /* for */
  986         result->writeTest.indexHash = newWriteIndexHash;
  987         result->iteratorMode = conv(source)->iteratorMode;
  988         result->iterEvents = conv(source)->iterEvents;
  989         result->numOfEvents = conv(source)->numOfEvents;
  990       } /* if */
  991     } /* if */
  992     logFunction(printf("polCreate -->\n"););
  993     /* dumpPoll((pollType) result); */
  994     return (pollType) result;
  995   } /* polCreate */
  996 
  997 
  998 
  999 /**
 1000  *  Free the memory referred by 'oldPollData'.
 1001  *  After polDestr is left 'oldPollData' refers to not existing memory.
 1002  *  The memory where 'oldPollData' is stored can be freed afterwards.
 1003  */
 1004 void polDestr (const pollType oldPollData)
 1005 
 1006   {
 1007     memSizeType capacity;
 1008     memSizeType pos;
 1009 
 1010   /* polDestr */
 1011     if (oldPollData != NULL) {
 1012       /* Free readTest */
 1013       for (pos = 0; pos < conv(oldPollData)->readTest.size; pos++) {
 1014         fileObjectOps.decrUsageCount(conv(oldPollData)->readTest.files[pos].file);
 1015       } /* for */
 1016       capacity = conv(oldPollData)->readTest.capacity;
 1017 #if DYNAMIC_FD_SET
 1018 #if USE_PREPARED_FD_SET
 1019       FREE_FDSET(conv(oldPollData)->readTest.inFdset, capacity);
 1020 #endif
 1021       FREE_FDSET(conv(oldPollData)->readTest.outFdset, capacity);
 1022 #endif
 1023       FREE_TABLE(conv(oldPollData)->readTest.files, fdAndFileType, capacity);
 1024       hshDestr(conv(oldPollData)->readTest.indexHash, (destrFuncType) &genericDestr,
 1025                (destrFuncType) &genericDestr);
 1026       /* Free writeTest */
 1027       for (pos = 0; pos < conv(oldPollData)->writeTest.size; pos++) {
 1028         fileObjectOps.decrUsageCount(conv(oldPollData)->writeTest.files[pos].file);
 1029       } /* for */
 1030       capacity = conv(oldPollData)->writeTest.capacity;
 1031 #if DYNAMIC_FD_SET
 1032 #if USE_PREPARED_FD_SET
 1033       FREE_FDSET(conv(oldPollData)->writeTest.inFdset, capacity);
 1034 #endif
 1035       FREE_FDSET(conv(oldPollData)->writeTest.outFdset, capacity);
 1036 #endif
 1037       FREE_TABLE(conv(oldPollData)->writeTest.files, fdAndFileType, capacity);
 1038       hshDestr(conv(oldPollData)->writeTest.indexHash, (destrFuncType) &genericDestr,
 1039                (destrFuncType) &genericDestr);
 1040       FREE_RECORD(var_conv(oldPollData), select_based_pollRecord, count.polldata);
 1041     } /* if */
 1042   } /* polDestr */
 1043 
 1044 
 1045 
 1046 /**
 1047  *  Create an empty poll data value.
 1048  *  @return an empty poll data value.
 1049  *  @exception MEMORY_ERROR Not enough memory for the result.
 1050  */
 1051 pollType polEmpty (void)
 1052 
 1053   {
 1054     rtlHashType newReadIndexHash;
 1055     rtlHashType newWriteIndexHash;
 1056     select_based_pollType result;
 1057 
 1058   /* polEmpty */
 1059     /* printf("polEmpty()\n"); */
 1060     newReadIndexHash = hshEmpty();
 1061     newWriteIndexHash = hshEmpty();
 1062     if (unlikely(newReadIndexHash == NULL || newWriteIndexHash == NULL ||
 1063                  !ALLOC_RECORD(result, select_based_pollRecord, count.polldata))) {
 1064       raise_error(MEMORY_ERROR);
 1065       result = NULL;
 1066     } else {
 1067       if (unlikely(!ALLOC_TABLE(result->readTest.files, fdAndFileType, TABLE_START_SIZE) ||
 1068                    !ALLOC_TABLE(result->writeTest.files, fdAndFileType, TABLE_START_SIZE) ||
 1069                    !allocFdSet(&result->readTest, TABLE_START_SIZE) ||
 1070                    !allocFdSet(&result->writeTest, TABLE_START_SIZE))) {
 1071         if (result->readTest.files != NULL) {
 1072           FREE_TABLE(result->readTest.files, fdAndFileType, TABLE_START_SIZE);
 1073           if (result->writeTest.files != NULL) {
 1074             FREE_TABLE(result->writeTest.files, fdAndFileType, TABLE_START_SIZE);
 1075             freeFdSet(&result->readTest, TABLE_START_SIZE);
 1076           } /* if */
 1077         } /* if */
 1078         FREE_RECORD(result, select_based_pollRecord, count.polldata);
 1079         raise_error(MEMORY_ERROR);
 1080         result = NULL;
 1081       } else {
 1082 #if USE_PREPARED_FD_SET
 1083         FD_ZERO(to_read_inFdset(result));
 1084         FD_ZERO(to_write_inFdset(result));
 1085 #if SELECT_WITH_NFDS
 1086         result->readTest.preparedNfds = 0;
 1087         result->writeTest.preparedNfds = 0;
 1088 #endif
 1089 #endif
 1090         FD_ZERO(to_read_outFdset(result));
 1091         FD_ZERO(to_write_outFdset(result));
 1092         result->readTest.size = 0;
 1093         result->readTest.capacity = TABLE_START_SIZE;
 1094         result->readTest.iterPos = 0;
 1095         result->readTest.indexHash = newReadIndexHash;
 1096         result->writeTest.size = 0;
 1097         result->writeTest.capacity = TABLE_START_SIZE;
 1098         result->writeTest.iterPos = 0;
 1099         result->writeTest.indexHash = newWriteIndexHash;
 1100         result->iteratorMode = ITER_EMPTY;
 1101         result->iterEvents = 0;
 1102         result->numOfEvents = 0;
 1103       } /* if */
 1104     } /* if */
 1105     /* printf("end polEmpty:\n");
 1106        dumpPoll((pollType) result); */
 1107     return (pollType) result;
 1108   } /* polEmpty */
 1109 
 1110 
 1111 
 1112 /**
 1113  *  Return the checkedEvents field from 'pollData' for 'aSocket'.
 1114  *  The polPoll function uses the checkedEvents as input.
 1115  *  The following checkedEvents can be returned:
 1116  *  - POLLNOTHING no data can be read or written.
 1117  *  - POLLIN data can be read from the corresponding socket.
 1118  *  - POLLOUT data can be written to the corresponding socket.
 1119  *  - POLLINOUT data can be read and written (POLLIN and POLLOUT).
 1120  *
 1121  *  @param pollData Poll data from which the checkedEvents are
 1122  *         retrieved.
 1123  *  @param aSocket Socket for which the checkedEvents are retrieved.
 1124  *  @return POLLNOTHING, POLLIN, POLLOUT or POLLINOUT, depending on
 1125  *          the events added and removed for 'aSocket' with
 1126  *          'addCheck' and 'removeCheck'.
 1127  */
 1128 intType polGetCheck (const const_pollType pollData, const socketType aSocket)
 1129 
 1130   {
 1131     intType result;
 1132 
 1133   /* polGetCheck */
 1134     if (isChecked(&conv(pollData)->readTest, aSocket)) {
 1135       if (isChecked(&conv(pollData)->writeTest, aSocket)) {
 1136         result = POLL_INOUT;
 1137       } else {
 1138         result = POLL_IN;
 1139       } /* if */
 1140     } else if (isChecked(&conv(pollData)->writeTest, aSocket)) {
 1141       result = POLL_OUT;
 1142     } else {
 1143       result = POLL_NOTHING;
 1144     } /* if */
 1145     return result;
 1146   } /* polGetCheck */
 1147 
 1148 
 1149 
 1150 /**
 1151  *  Return the eventFindings field from 'pollData' for 'aSocket'.
 1152  *  The polPoll function assigns the
 1153  *  eventFindings for 'aSocket' to 'pollData'. The following
 1154  *  eventFindings can be returned:
 1155  *  - POLLNOTHING no data can be read or written.
 1156  *  - POLLIN data can be read from the corresponding socket.
 1157  *  - POLLOUT data can be written to the corresponding socket.
 1158  *  - POLLINOUT data can be read and written (POLLIN and POLLOUT).
 1159  *
 1160  *  @return POLLNOTHING, POLLIN, POLLOUT or POLLINOUT, depending on
 1161  *          the findings of polPoll concerning 'aSocket'.
 1162  */
 1163 intType polGetFinding (const const_pollType pollData, const socketType aSocket)
 1164 
 1165   {
 1166     intType result;
 1167 
 1168   /* polGetFinding */
 1169     if (isReady(&conv(pollData)->readTest, aSocket)) {
 1170       if (isReady(&conv(pollData)->writeTest, aSocket)) {
 1171         result = POLL_INOUT;
 1172       } else {
 1173         result = POLL_IN;
 1174       } /* if */
 1175     } else if (isReady(&conv(pollData)->writeTest, aSocket)) {
 1176       result = POLL_OUT;
 1177     } else {
 1178       result = POLL_NOTHING;
 1179     } /* if */
 1180     return result;
 1181   } /* polGetFinding */
 1182 
 1183 
 1184 
 1185 /**
 1186  *  Determine if the 'pollData' iterator can deliver another file.
 1187  *  @return TRUE if 'nextFile' would return another file from the
 1188  *          'pollData' iterator, FALSE otherwise.
 1189  */
 1190 boolType polHasNext (const pollType pollData)
 1191 
 1192   { /* polHasNext */
 1193     switch (conv(pollData)->iteratorMode) {
 1194       case ITER_CHECKS_IN:
 1195         return hasNextCheck(&conv(pollData)->readTest);
 1196       case ITER_CHECKS_OUT:
 1197         return hasNextCheck(&conv(pollData)->writeTest);
 1198       case ITER_CHECKS_INOUT:
 1199         return hasNextCheck(&conv(pollData)->readTest) ||
 1200                hasNextCheck(&conv(pollData)->writeTest);
 1201       case ITER_FINDINGS_IN:
 1202         return hasNextFinding(&var_conv(pollData)->readTest,
 1203                               conv(pollData)->iterEvents);
 1204       case ITER_FINDINGS_OUT:
 1205         return hasNextFinding(&var_conv(pollData)->writeTest,
 1206                               conv(pollData)->iterEvents);
 1207       case ITER_FINDINGS_INOUT:
 1208         return hasNextFinding(&var_conv(pollData)->readTest,
 1209                               conv(pollData)->iterEvents) ||
 1210                hasNextFinding(&var_conv(pollData)->writeTest,
 1211                               conv(pollData)->iterEvents);
 1212       case ITER_EMPTY:
 1213       default:
 1214         return FALSE;
 1215     } /* switch */
 1216   } /* polHasNext */
 1217 
 1218 
 1219 
 1220 /**
 1221  *  Reset the 'pollData' iterator to process checkedEvents.
 1222  *  The following calls of 'hasNext' and 'nextFile' refer to
 1223  *  the checkedEvents of the given 'pollMode'. 'PollMode'
 1224  *  can have one of the following values:
 1225  *  - POLLNOTHING don't iterate ('hasNext' returns FALSE).
 1226  *  - POLLIN data can be read from the corresponding socket.
 1227  *  - POLLOUT data can be written to the corresponding socket.
 1228  *  - POLLINOUT data can be read or written (POLLIN and POLLOUT).
 1229  *
 1230  *  @exception RANGE_ERROR Illegal value for 'pollMode'.
 1231  */
 1232 void polIterChecks (const pollType pollData, intType pollMode)
 1233 
 1234   { /* polIterChecks */
 1235     switch (castIntTypeForSwitch(pollMode)) {
 1236       case POLL_NOTHING:
 1237         var_conv(pollData)->iteratorMode = ITER_EMPTY;
 1238         break;
 1239       case POLL_IN:
 1240         var_conv(pollData)->iteratorMode = ITER_CHECKS_IN;
 1241         var_conv(pollData)->readTest.iterPos = 0;
 1242         break;
 1243       case POLL_OUT:
 1244         var_conv(pollData)->iteratorMode = ITER_CHECKS_OUT;
 1245         var_conv(pollData)->writeTest.iterPos = 0;
 1246         break;
 1247       case POLL_INOUT:
 1248         var_conv(pollData)->iteratorMode = ITER_CHECKS_INOUT;
 1249         var_conv(pollData)->readTest.iterPos = 0;
 1250         var_conv(pollData)->writeTest.iterPos = 0;
 1251         break;
 1252       default:
 1253         raise_error(RANGE_ERROR);
 1254         break;
 1255     } /* switch */
 1256   } /* polIterChecks */
 1257 
 1258 
 1259 
 1260 /**
 1261  *  Reset the 'pollData' iterator to process eventFindings.
 1262  *  The following calls of 'hasNext' and 'nextFile' refer to
 1263  *  the eventFindings of the given 'pollMode'. 'PollMode'
 1264  *  can have one of the following values:
 1265  *  - POLLNOTHING don't iterate ('hasNext' returns FALSE).
 1266  *  - POLLIN data can be read from the corresponding socket.
 1267  *  - POLLOUT data can be written to the corresponding socket.
 1268  *  - POLLINOUT data can be read or written (POLLIN and POLLOUT).
 1269  *
 1270  *  @exception RANGE_ERROR Illegal value for 'pollMode'.
 1271  */
 1272 void polIterFindings (const pollType pollData, intType pollMode)
 1273 
 1274   { /* polIterFindings */
 1275     switch (castIntTypeForSwitch(pollMode)) {
 1276       case POLL_NOTHING:
 1277         var_conv(pollData)->iteratorMode = ITER_EMPTY;
 1278         break;
 1279       case POLL_IN:
 1280         var_conv(pollData)->iteratorMode = ITER_FINDINGS_IN;
 1281         var_conv(pollData)->readTest.iterPos = 0;
 1282         break;
 1283       case POLL_OUT:
 1284         var_conv(pollData)->iteratorMode = ITER_FINDINGS_OUT;
 1285         var_conv(pollData)->writeTest.iterPos = 0;
 1286         break;
 1287       case POLL_INOUT:
 1288         var_conv(pollData)->iteratorMode = ITER_FINDINGS_INOUT;
 1289         var_conv(pollData)->readTest.iterPos = 0;
 1290         var_conv(pollData)->writeTest.iterPos = 0;
 1291         break;
 1292       default:
 1293         raise_error(RANGE_ERROR);
 1294         break;
 1295     } /* switch */
 1296     var_conv(pollData)->iterEvents = conv(pollData)->numOfEvents;
 1297   } /* polIterFindings */
 1298 
 1299 
 1300 
 1301 /**
 1302  *  Get the next file from the 'pollData' iterator.
 1303  *  Successive calls of 'nextFile' return all files from the 'pollData'
 1304  *  iterator. The file returned by 'nextFile' is determined with the
 1305  *  function 'addCheck'. The files covered by the 'pollData' iterator
 1306  *  are determined with 'iterChecks' or 'iterFindings'.
 1307  *  @return the next file from the 'pollData' iterator, or
 1308  *          STD_NULL if no file from the 'pollData' iterator is available.
 1309  */
 1310 genericType polNextFile (const pollType pollData, const genericType nullFile)
 1311 
 1312   {
 1313     genericType nextFile;
 1314 
 1315   /* polNextFile */
 1316     switch (conv(pollData)->iteratorMode) {
 1317       case ITER_CHECKS_IN:
 1318         nextFile = nextCheck(&var_conv(pollData)->readTest, nullFile);
 1319         break;
 1320       case ITER_CHECKS_OUT:
 1321         nextFile = nextCheck(&var_conv(pollData)->writeTest, nullFile);
 1322         break;
 1323       case ITER_CHECKS_INOUT:
 1324         if (hasNextCheck(&conv(pollData)->readTest)) {
 1325           nextFile = nextCheck(&var_conv(pollData)->readTest, nullFile);
 1326         } else {
 1327           nextFile = nextCheck(&var_conv(pollData)->writeTest, nullFile);
 1328         } /* if */
 1329         break;
 1330       case ITER_FINDINGS_IN:
 1331         nextFile = nextFinding(&var_conv(pollData)->readTest,
 1332                            &var_conv(pollData)->iterEvents, nullFile);
 1333         break;
 1334       case ITER_FINDINGS_OUT:
 1335         nextFile = nextFinding(&var_conv(pollData)->writeTest,
 1336                            &var_conv(pollData)->iterEvents, nullFile);
 1337         break;
 1338       case ITER_FINDINGS_INOUT:
 1339         if (hasNextFinding(&var_conv(pollData)->readTest,
 1340                            conv(pollData)->iterEvents)) {
 1341           nextFile = nextFinding(&var_conv(pollData)->readTest,
 1342                              &var_conv(pollData)->iterEvents, nullFile);
 1343         } else {
 1344           nextFile = nextFinding(&var_conv(pollData)->writeTest,
 1345                              &var_conv(pollData)->iterEvents, nullFile);
 1346         } /* if */
 1347         break;
 1348       case ITER_EMPTY:
 1349       default:
 1350         nextFile = nullFile;
 1351         break;
 1352     } /* switch */
 1353     return nextFile;
 1354   } /* polNextFile */
 1355 
 1356 
 1357 
 1358 /**
 1359  *  Waits for one or more of the checkedEvents from 'pollData'.
 1360  *  polPoll waits until one of the checkedEvents for a
 1361  *  corresponding socket occurs. If a checked event occurs
 1362  *  the eventFindings field is assigned a value. The following
 1363  *  eventFindings values are assigned:
 1364  *  - POLLIN data can be read from the corresponding socket.
 1365  *  - POLLOUT data can be written to the corresponding socket.
 1366  *  - POLLINOUT data can be read and written (POLLIN and POLLOUT).
 1367  *
 1368  *  @exception FILE_ERROR The system function returns an error.
 1369  */
 1370 void polPoll (const pollType pollData)
 1371 
 1372   { /* polPoll */
 1373     doPoll(pollData, NULL);
 1374   } /* polPoll */
 1375 
 1376 
 1377 
 1378 /**
 1379  *  Remove 'eventsToCheck' for 'aSocket' from 'pollData'.
 1380  *  'EventsToCheck' can have one of the following values:
 1381  *  - POLLIN check if data can be read from the corresponding socket.
 1382  *  - POLLOUT check if data can be written to the corresponding socket.
 1383  *  - POLLINOUT check if data can be read or written (POLLIN or POLLOUT).
 1384  *
 1385  *  @param pData Poll data from which the event checks are removed.
 1386  *  @param aSocket Socket for which the events should not be checked.
 1387  *  @param eventsToCheck Events to be removed from the checkedEvents
 1388  *         field of 'pData'.
 1389  *  @exception RANGE_ERROR Illegal value for 'eventsToCheck'.
 1390  */
 1391  void polRemoveCheck (const pollType pollData, const socketType aSocket,
 1392     intType eventsToCheck)
 1393 
 1394   { /* polRemoveCheck */
 1395     switch (castIntTypeForSwitch(eventsToCheck)) {
 1396       case POLL_IN:
 1397         removeCheck(&var_conv(pollData)->readTest, aSocket);
 1398         break;
 1399       case POLL_OUT:
 1400         removeCheck(&var_conv(pollData)->writeTest, aSocket);
 1401         break;
 1402       case POLL_INOUT:
 1403         removeCheck(&var_conv(pollData)->readTest, aSocket);
 1404         removeCheck(&var_conv(pollData)->writeTest, aSocket);
 1405         break;
 1406       default:
 1407         raise_error(RANGE_ERROR);
 1408         break;
 1409     } /* switch */
 1410   } /* polRemoveCheck */