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

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.2 ! cbrooks   200:     int cnt; int i;
2.1       frystyk   201:     if (THD_TRACE)
2.7       frystyk   202:        fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
2.7.2.1   frystyk   203: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks   204:        for (i = 0 ; i < HTfd_set.fd_count; i++) {      cnt = HTfd_set.fd_array[i];     if (
2.7.2.1   frystyk   205: #else
2.7.2.2 ! cbrooks   206:     for (cnt=0; cnt<HTMaxfdpl; cnt++) {         if (FD_ISSET(cnt, &HTfd_set) && 
        !           207: #endif
        !           208:                !FD_ISSET(cnt, fd_user))
2.4       frystyk   209:            FD_SET(cnt, &HTfd_intr);
2.2       frystyk   210:     }
2.1       frystyk   211: }
                    212: 
                    213: 
                    214: /*                                                              HTThreadActive
                    215: **
                    216: **     Returns yes as long as a socket other than stdin is registered in 
                    217: **     the total set of sockets.
                    218: */
                    219: PUBLIC BOOL HTThreadActive NOARGS
                    220: {
                    221:     int cnt;
2.7.2.1   frystyk   222: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks   223:        if (HTfd_set.fd_count > 0)
        !           224:                return YES;
2.7.2.1   frystyk   225: #else
2.1       frystyk   226:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
                    227:        if (FD_ISSET(cnt, &HTfd_set))
                    228:            return YES;
2.7.2.1   frystyk   229: #endif
2.1       frystyk   230:     return NO;
                    231: }
                    232: 
                    233: 
                    234: /*                                                                HTThread_new
                    235: **
                    236: **     Register the HTNetInfo structure in a list so that we can find the 
                    237: **     request which corresponds to a socket descriptor
                    238: */
                    239: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
                    240: {
                    241:     if (!HTThreads)
2.7.2.2 ! cbrooks   242:                HTThreads = HTList_new();
2.1       frystyk   243:     HTList_addObject(HTThreads, (void *) new_net);
                    244: }
                    245: 
                    246: 
                    247: /*                                                              HTThread_clear
                    248: **
                    249: **     Remove the HTNetInfo from the list of acrive threads.
                    250: */
                    251: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
                    252: {
                    253:     if (HTThreads)
2.7.2.2 ! cbrooks   254:                return HTList_removeObject(HTThreads, (void *) old_net);
2.1       frystyk   255:     return NO;
                    256: }
                    257: 
                    258: 
                    259: /*                                                        HTThread_getCallBack
                    260: **
                    261: **     Finds a socket and makes it the active thread. READ has a higher
                    262: **     priority than WRITE as it might influence (stop) the WRITE process.
                    263: **     Returns the request structure of the active thread, NULL on error.
                    264: **     A interrupted socket has the highest priority
                    265: */
                    266: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *,    fd_read,
                    267:                                            CONST fd_set *,     fd_write)
                    268: {
                    269:     HTList *cur = HTThreads;
                    270:     HTNetInfo *pres;
2.7.2.1   frystyk   271:     int cnt;
2.7.2.2 ! cbrooks   272:        int ic = 0 ;
2.1       frystyk   273:     BOOL found = NO;
2.7.2.1   frystyk   274: 
                    275: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks   276:        for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic]; 
2.7.2.1   frystyk   277: #else
2.1       frystyk   278:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
2.7.2.1   frystyk   279: #endif
2.1       frystyk   280:        if (FD_ISSET(cnt, &HTfd_intr)) {
                    281:            if (THD_TRACE)
2.7       frystyk   282:                fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
2.1       frystyk   283:            found = YES;
                    284:            break;
                    285:        }
                    286:     }
                    287:     if (!found) {
2.7.2.1   frystyk   288: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks   289:        for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic]; 
2.7.2.1   frystyk   290: #else
2.7.2.2 ! cbrooks   291:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
2.7.2.1   frystyk   292: #endif
2.1       frystyk   293:            if (FD_ISSET(cnt, fd_read)) {
                    294:                if (THD_TRACE)
2.7       frystyk   295:                    fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
2.1       frystyk   296:                found = YES;
                    297:                break;
                    298:            }
                    299:        }
                    300:     }
                    301:     if (!found) {
2.7.2.1   frystyk   302: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks   303:        for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic]; 
2.7.2.1   frystyk   304: #else
2.7.2.2 ! cbrooks   305:     for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) {           /* INTERRUPT */
2.7.2.1   frystyk   306: #endif
2.1       frystyk   307:            if (FD_ISSET(cnt, fd_write)) {
                    308:                if (THD_TRACE)
2.7       frystyk   309:                    fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
2.1       frystyk   310:                found = YES;
                    311:                break;
                    312:            }
                    313:        }
                    314:     }
                    315:     if (!found || cur == NULL)
2.7.2.2 ! cbrooks   316:                return NULL;
2.1       frystyk   317: 
                    318:     /* Find the corresponding HTNetInfo structure */
                    319:     while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
2.7.2.2 ! cbrooks   320:                if (pres->sockfd == cnt) {
2.1       frystyk   321:            return pres->request;
2.7.2.2 ! cbrooks   322:                }
2.1       frystyk   323:     }
                    324:     return NULL;
                    325: }

Webmaster