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

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

Webmaster