Annotation of libwww/Library/src/HTNet.c, revision 2.1
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:
! 121: case THD_INTR:
! 122: FD_CLR(sockfd, &HTfd_read);
! 123: FD_CLR(sockfd, &HTfd_write);
! 124: FD_SET(sockfd, &HTfd_intr);
! 125: break;
! 126:
! 127: default:
! 128: if (THD_TRACE)
! 129: fprintf(stderr, "Thread...... Illigal socket action\n");
! 130: }
! 131:
! 132: /* Update max bit width. The method used ignores any other default
! 133: opened file descriptors between STDERR_FILENO and the actual set
! 134: of file descriptors used. However, they are not registered anyway */
! 135: if (action == THD_CLOSE) {
! 136: if (sockfd+1 >= HTMaxfdpl) {
! 137: while (HTMaxfdpl > STDERR_FILENO+1 &&
! 138: !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
! 139: HTMaxfdpl--;
! 140: }
! 141: } else {
! 142: if (sockfd+1 > HTMaxfdpl)
! 143: HTMaxfdpl = sockfd+1;
! 144: }
! 145: if (THD_TRACE)
! 146: fprintf(stderr, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
! 147: }
! 148:
! 149:
! 150: /* HTThreadIntr
! 151: **
! 152: ** This function returns YES or NO to the question
! 153: */
! 154: PUBLIC BOOL HTThreadIntr ARGS1(int, sockfd)
! 155: {
! 156: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
! 157: }
! 158:
! 159:
! 160: /* HTThreadMarkIntrAll
! 161: **
! 162: ** Marks all sockets as interrupted
! 163: */
! 164: PUBLIC void HTThreadMarkIntrAll NOARGS
! 165: {
! 166: int cnt;
! 167: if (THD_TRACE)
! 168: fprintf(stderr, "Thread...... Mark all sockets as INTERRUPTED\n");
! 169: for (cnt=STDERR_FILENO+1; cnt<HTMaxfdpl; cnt++)
! 170: FD_SET(cnt, &HTfd_intr);
! 171: }
! 172:
! 173:
! 174: /* HTThreadActive
! 175: **
! 176: ** Returns yes as long as a socket other than stdin is registered in
! 177: ** the total set of sockets.
! 178: */
! 179: PUBLIC BOOL HTThreadActive NOARGS
! 180: {
! 181: int cnt;
! 182: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
! 183: if (FD_ISSET(cnt, &HTfd_set))
! 184: return YES;
! 185: return NO;
! 186: }
! 187:
! 188:
! 189: /* HTThread_new
! 190: **
! 191: ** Register the HTNetInfo structure in a list so that we can find the
! 192: ** request which corresponds to a socket descriptor
! 193: */
! 194: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
! 195: {
! 196: if (!HTThreads)
! 197: HTThreads = HTList_new();
! 198: HTList_addObject(HTThreads, (void *) new_net);
! 199: }
! 200:
! 201:
! 202: /* HTThread_clear
! 203: **
! 204: ** Remove the HTNetInfo from the list of acrive threads.
! 205: */
! 206: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
! 207: {
! 208: if (HTThreads)
! 209: return HTList_removeObject(HTThreads, (void *) old_net);
! 210: return NO;
! 211: }
! 212:
! 213:
! 214: /* HTThread_getCallBack
! 215: **
! 216: ** Finds a socket and makes it the active thread. READ has a higher
! 217: ** priority than WRITE as it might influence (stop) the WRITE process.
! 218: ** Returns the request structure of the active thread, NULL on error.
! 219: ** A interrupted socket has the highest priority
! 220: */
! 221: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *, fd_read,
! 222: CONST fd_set *, fd_write)
! 223: {
! 224: HTList *cur = HTThreads;
! 225: HTNetInfo *pres;
! 226: int cnt;
! 227: BOOL found = NO;
! 228: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
! 229: if (FD_ISSET(cnt, &HTfd_intr)) {
! 230: if (THD_TRACE)
! 231: fprintf(stderr, "GetSocket... Socket %d INTERRUPTED\n", cnt);
! 232: found = YES;
! 233: break;
! 234: }
! 235: }
! 236: if (!found) {
! 237: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* READ */
! 238: if (FD_ISSET(cnt, fd_read)) {
! 239: if (THD_TRACE)
! 240: fprintf(stderr, "GetSocket... Socket %d for READ\n", cnt);
! 241: found = YES;
! 242: break;
! 243: }
! 244: }
! 245: }
! 246: if (!found) {
! 247: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* WRITE */
! 248: if (FD_ISSET(cnt, fd_write)) {
! 249: if (THD_TRACE)
! 250: fprintf(stderr, "GetSocket... Socket %d for WRITE\n", cnt);
! 251: found = YES;
! 252: break;
! 253: }
! 254: }
! 255: }
! 256: if (!found || cur == NULL)
! 257: return NULL;
! 258:
! 259: /* Find the corresponding HTNetInfo structure */
! 260: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
! 261: if (pres->sockfd == cnt) {
! 262: return pres->request;
! 263: }
! 264: }
! 265: return NULL;
! 266: }
Webmaster