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

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

Webmaster