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

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

Webmaster