Annotation of libwww/Library/src/HTNet.c, revision 2.2

2.1       frystyk     1: /*                     Multiple Thread Socket Management
                      2: **                     =================================
                      3: **
                      4: **     This is the implementation of the internal library multi-threading
                      5: **     functions. This includes an interrupt handler and a event loop.
                      6: **     
                      7: ** History:
                      8: **     12 June 94      Written by Henrik Frystyk, frystyk@dxcern.cern.ch
                      9: */
                     10: 
                     11: /* Implemention dependent include files */
                     12: #include "tcp.h"
                     13: 
                     14: /* Library include files */
                     15: #include "HTUtils.h"
                     16: #include "HTAccess.h"
                     17: #include "HTError.h"
                     18: #include "HTThread.h"                                   /* Implemented here */
                     19: 
                     20: /* Type definitions and global variables etc. local to this module */
                     21: PRIVATE fd_set HTfd_read;            /* Bit array of sockets ready for read */
                     22: PRIVATE fd_set HTfd_write;          /* Bit array of sockets ready for write */
                     23: PRIVATE int    HTMaxfdpl = 0;                  /* Max number of sockets + 1 */
                     24: 
                     25: PRIVATE fd_set HTfd_intr;              /* All sockets currently interrupted */
                     26: PRIVATE fd_set HTfd_set;                /* All sockets currently registered */
                     27: 
                     28: PRIVATE HTList *HTThreads = NULL;               /* List of the HTNetInfo structures */
                     29: 
                     30: /* ------------------------------------------------------------------------- */
                     31: 
                     32: /*                                                                HTThreadInit
                     33: **
                     34: **     Initiates the thread socket registers. It is very important that
                     35: **     this function is called. It is currently done inside HTAccess in the
                     36: **     HTAccessInit function.
                     37: */
                     38: PUBLIC BOOL HTThreadInit NOARGS
                     39: {
                     40:     static BOOL done=NO;
                     41: 
                     42:     if (done) {
                     43:        if (THD_TRACE)
                     44:            fprintf(stderr, "ThreadInit.. Already done\n");
                     45:        return NO;
                     46:     }
                     47:     done = YES;
                     48: 
                     49:     /* Initialize the other internal bit arrays */
                     50:     FD_ZERO(&HTfd_write);
                     51:     FD_ZERO(&HTfd_set);
                     52:     FD_ZERO(&HTfd_intr);
                     53:     return YES;
                     54: }
                     55: 
                     56: 
                     57: /*                                                           HTThreadGetFDInfo
                     58: **
                     59: **     Returns the maximum bit width and the read and write bit array.
                     60: */
                     61: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
                     62: {
                     63:     *read = HTfd_read;
                     64:     *write = HTfd_write;
                     65:     return HTMaxfdpl;
                     66: }
                     67: 
                     68: 
                     69: /*                                                               HTThreadState
                     70: **
                     71: **     This function registers a socket as waiting for the action given
                     72: **     (read or write etc.).
                     73: */
                     74: PUBLIC void HTThreadState ARGS2(int, sockfd, HTThreadAction, action)
                     75: {
                     76:     if (THD_TRACE) {
                     77:        static char *actionmsg[] = {
                     78:            "SET WRITE",
                     79:            "CLEAR WRITE",
                     80:            "SET READ",
                     81:            "CLEAR READ",
                     82:            "INTERRUPT",
                     83:            "CLOSE"
                     84:            };
                     85:        fprintf(stderr,
                     86:                "Thread...... Register socket number %d for action %s\n",
                     87:                sockfd, *(actionmsg+action));
                     88:     }
                     89:     switch (action) {
                     90:       case THD_SET_WRITE:
                     91:        FD_CLR(sockfd, &HTfd_read);
                     92:        FD_SET(sockfd, &HTfd_write);
                     93:        FD_SET(sockfd, &HTfd_set);
                     94:        break;
                     95: 
                     96:       case THD_CLR_WRITE:
                     97:        FD_CLR(sockfd, &HTfd_read);
                     98:        FD_CLR(sockfd, &HTfd_write);
                     99:        FD_CLR(sockfd, &HTfd_set);
                    100:        break;
                    101: 
                    102:       case THD_SET_READ:
                    103:        FD_SET(sockfd, &HTfd_read);
                    104:        FD_CLR(sockfd, &HTfd_write);
                    105:        FD_SET(sockfd, &HTfd_set);
                    106:        break;
                    107: 
                    108:       case THD_CLR_READ:
                    109:        FD_CLR(sockfd, &HTfd_read);
                    110:        FD_CLR(sockfd, &HTfd_write);
                    111:        FD_CLR(sockfd, &HTfd_set);
                    112:        break;
                    113: 
                    114:       case THD_CLOSE:
                    115:        FD_CLR(sockfd, &HTfd_read);
                    116:        FD_CLR(sockfd, &HTfd_write);
                    117:        FD_CLR(sockfd, &HTfd_intr);
                    118:        FD_CLR(sockfd, &HTfd_set);
                    119:        break;
                    120: 
2.2     ! frystyk   121:       case THD_SET_INTR:
2.1       frystyk   122:        FD_CLR(sockfd, &HTfd_read);
                    123:        FD_CLR(sockfd, &HTfd_write);
                    124:        FD_SET(sockfd, &HTfd_intr);
                    125:        break;
                    126: 
2.2     ! frystyk   127:       case THD_CLR_INTR:
        !           128:        FD_CLR(sockfd, &HTfd_intr);
        !           129:        break;
        !           130: 
2.1       frystyk   131:       default:
                    132:        if (THD_TRACE)
                    133:            fprintf(stderr, "Thread...... Illigal socket action\n");
                    134:     }
                    135: 
                    136:     /* Update max bit width. The method used ignores any other default
2.2     ! frystyk   137:        opened file descriptors between 0 and the actual set of file
        !           138:        descriptors used. However, they are not registered anyway */
2.1       frystyk   139:     if (action == THD_CLOSE) {
                    140:        if (sockfd+1 >= HTMaxfdpl) {
2.2     ! frystyk   141:            while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
2.1       frystyk   142:                HTMaxfdpl--;
                    143:        }
                    144:     } else {
                    145:        if (sockfd+1 > HTMaxfdpl)
                    146:            HTMaxfdpl = sockfd+1;
                    147:     }
                    148:     if (THD_TRACE)
                    149:        fprintf(stderr, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
                    150: }
                    151: 
                    152: 
                    153: /*                                                                HTThreadIntr
                    154: **
                    155: **     This function returns YES or NO to the question
                    156: */
                    157: PUBLIC BOOL HTThreadIntr ARGS1(int, sockfd)
                    158: {
                    159:     return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
                    160: }
                    161: 
                    162: 
                    163: /*                                                         HTThreadMarkIntrAll
                    164: **
2.2     ! frystyk   165: **     Marks all Library sockets as interrupted. User sockets can not be
        !           166: **     interrupted
2.1       frystyk   167: */
2.2     ! frystyk   168: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *,  fd_user)
2.1       frystyk   169: {
                    170:     int cnt;
                    171:     if (THD_TRACE)
2.2     ! frystyk   172:        fprintf(stderr, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
        !           173:     for (cnt=0; cnt<HTMaxfdpl; cnt++) {
        !           174:        if (!FD_ISSET(cnt, fd_user)) FD_SET(cnt, &HTfd_intr);
        !           175:     }
2.1       frystyk   176: }
                    177: 
                    178: 
                    179: /*                                                              HTThreadActive
                    180: **
                    181: **     Returns yes as long as a socket other than stdin is registered in 
                    182: **     the total set of sockets.
                    183: */
                    184: PUBLIC BOOL HTThreadActive NOARGS
                    185: {
                    186:     int cnt;
                    187:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
                    188:        if (FD_ISSET(cnt, &HTfd_set))
                    189:            return YES;
                    190:     return NO;
                    191: }
                    192: 
                    193: 
                    194: /*                                                                HTThread_new
                    195: **
                    196: **     Register the HTNetInfo structure in a list so that we can find the 
                    197: **     request which corresponds to a socket descriptor
                    198: */
                    199: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
                    200: {
                    201:     if (!HTThreads)
                    202:        HTThreads = HTList_new();
                    203:     HTList_addObject(HTThreads, (void *) new_net);
                    204: }
                    205: 
                    206: 
                    207: /*                                                              HTThread_clear
                    208: **
                    209: **     Remove the HTNetInfo from the list of acrive threads.
                    210: */
                    211: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
                    212: {
                    213:     if (HTThreads)
                    214:        return HTList_removeObject(HTThreads, (void *) old_net);
                    215:     return NO;
                    216: }
                    217: 
                    218: 
                    219: /*                                                        HTThread_getCallBack
                    220: **
                    221: **     Finds a socket and makes it the active thread. READ has a higher
                    222: **     priority than WRITE as it might influence (stop) the WRITE process.
                    223: **     Returns the request structure of the active thread, NULL on error.
                    224: **     A interrupted socket has the highest priority
                    225: */
                    226: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *,    fd_read,
                    227:                                            CONST fd_set *,     fd_write)
                    228: {
                    229:     HTList *cur = HTThreads;
                    230:     HTNetInfo *pres;
                    231:     int cnt;
                    232:     BOOL found = NO;
                    233:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
                    234:        if (FD_ISSET(cnt, &HTfd_intr)) {
                    235:            if (THD_TRACE)
                    236:                fprintf(stderr, "GetSocket... Socket %d INTERRUPTED\n", cnt);
2.2     ! frystyk   237:            HTThreadState(cnt, THD_CLR_INTR);           /* Only called once! */
2.1       frystyk   238:            found = YES;
                    239:            break;
                    240:        }
                    241:     }
                    242:     if (!found) {
                    243:        for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {             /* READ */
                    244:            if (FD_ISSET(cnt, fd_read)) {
                    245:                if (THD_TRACE)
                    246:                    fprintf(stderr, "GetSocket... Socket %d for READ\n", cnt);
                    247:                found = YES;
                    248:                break;
                    249:            }
                    250:        }
                    251:     }
                    252:     if (!found) {
                    253:        for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {            /* WRITE */
                    254:            if (FD_ISSET(cnt, fd_write)) {
                    255:                if (THD_TRACE)
                    256:                    fprintf(stderr, "GetSocket... Socket %d for WRITE\n", cnt);
                    257:                found = YES;
                    258:                break;
                    259:            }
                    260:        }
                    261:     }
                    262:     if (!found || cur == NULL)
                    263:        return NULL;
                    264: 
                    265:     /* Find the corresponding HTNetInfo structure */
                    266:     while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
                    267:        if (pres->sockfd == cnt) {
                    268:            return pres->request;
                    269:        }
                    270:     }
                    271:     return NULL;
                    272: }

Webmaster