Annotation of libwww/Library/src/HTNet.c, revision 2.10.2.1
2.10.2.1! cbrooks 1: /* HTThread.c
! 2: ** MULTIPLE THREAD SOCKET MANAGEMENT
! 3: **
! 4: ** (c) COPYRIGHT MIT 1995.
! 5: ** Please first read the full copyright statement in the file COPYRIGH.
! 6: **
! 7: ** This is the implementation of the internal library multithreading
! 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: #ifdef WIN32
! 24: #include <io.h>
! 25: #endif
! 26:
! 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:
! 35:
! 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)
! 52: fprintf(TDEST, "ThreadInit.. Already done\n");
! 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);
! 61: FD_ZERO(&HTfd_read) ;
! 62:
! 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: */
! 84: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
! 85: {
! 86: #ifdef _WIN32
! 87: if (sockfd <= 2)
! 88: sockfd = _get_osfhandle(sockfd) ;
! 89: #endif
! 90:
! 91: if (THD_TRACE) {
! 92: static char *actionmsg[] = {
! 93: "SET WRITE",
! 94: "CLEAR WRITE",
! 95: "SET READ",
! 96: "CLEAR READ",
! 97: "SET INTERRUPT",
! 98: "CLEAR INTERRUPT",
! 99: "CLOSE"
! 100: };
! 101: fprintf(TDEST,
! 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);
! 108: if (! FD_ISSET(sockfd, &HTfd_write))
! 109: FD_SET(sockfd, &HTfd_write);
! 110: if (! FD_ISSET(sockfd, &HTfd_set))
! 111: FD_SET(sockfd, &HTfd_set);
! 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:
! 121: if (! FD_ISSET(sockfd, &HTfd_read))
! 122: FD_SET(sockfd, &HTfd_read);
! 123: FD_CLR(sockfd, &HTfd_write);
! 124: if (! FD_ISSET(sockfd, &HTfd_set))
! 125: FD_SET(sockfd, &HTfd_set);
! 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:
! 141: case THD_SET_INTR:
! 142: FD_CLR(sockfd, &HTfd_read);
! 143: FD_CLR(sockfd, &HTfd_write);
! 144: if (! FD_ISSET(sockfd, &HTfd_intr))
! 145: FD_SET(sockfd, &HTfd_intr);
! 146: break;
! 147:
! 148: case THD_CLR_INTR:
! 149: FD_CLR(sockfd, &HTfd_intr);
! 150: break;
! 151:
! 152: default:
! 153: if (THD_TRACE)
! 154: fprintf(TDEST, "Thread...... Illigal socket action\n");
! 155: }
! 156:
! 157: /* Update max bit width. The method used ignores any other default
! 158: opened file descriptors between 0 and the actual set of file
! 159: descriptors used. However, they are not registered anyway */
! 160:
! 161: if (action == THD_CLOSE) {
! 162: #ifdef _WINSOCKAPI_
! 163: HTMaxfdpl = HTfd_set.fd_count ;
! 164: #else
! 165: if (sockfd+1 >= HTMaxfdpl) {
! 166: while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
! 167: HTMaxfdpl--;
! 168: }
! 169: #endif
! 170: } else {
! 171: #ifdef _WINSOCKAPI_
! 172: HTMaxfdpl = HTfd_set.fd_count;
! 173: #else
! 174: if (sockfd+1 > HTMaxfdpl)
! 175: HTMaxfdpl = sockfd+1;
! 176: #endif
! 177: }
! 178: if (THD_TRACE)
! 179: fprintf(TDEST, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
! 180: }
! 181:
! 182:
! 183: /* HTThreadIntr
! 184: **
! 185: ** This function returns YES or NO to the question
! 186: */
! 187: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
! 188: {
! 189: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
! 190: }
! 191:
! 192:
! 193: /* HTThreadMarkIntrAll
! 194: **
! 195: ** Marks all Library sockets as interrupted. User sockets can not be
! 196: ** interrupted
! 197: */
! 198: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *, fd_user)
! 199: {
! 200: int cnt;
! 201: #ifdef _WINSOCKAPI_
! 202: int i;
! 203: #endif
! 204: if (THD_TRACE)
! 205: fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
! 206: #ifdef _WINSOCKAPI_
! 207: for (i = 0 ; i < HTfd_set.fd_count; i++) {
! 208: cnt = HTfd_set.fd_array[i];
! 209: if (!FD_ISSET(cnt, fd_user))
! 210: #else
! 211: for (cnt=0; cnt<HTMaxfdpl; cnt++) {
! 212: if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
! 213: #endif
! 214: FD_SET(cnt, &HTfd_intr);
! 215: }
! 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;
! 227: #ifdef _WINSOCKAPI_
! 228: if (HTfd_set.fd_count > 0)
! 229: return YES;
! 230: #else
! 231: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
! 232: if (FD_ISSET(cnt, &HTfd_set))
! 233: return YES;
! 234: #endif
! 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)
! 247: HTThreads = HTList_new();
! 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)
! 259: return HTList_removeObject(HTThreads, (void *) old_net);
! 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;
! 276: SOCKFD cnt;
! 277: SocAction found = SOC_INVALID;
! 278:
! 279: #ifdef _WINSOCKAPI_
! 280: int ic = 0;
! 281: #endif
! 282:
! 283: #ifdef _WINSOCKAPI_
! 284: for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic];
! 285: #else
! 286: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
! 287: #endif
! 288: if (FD_ISSET(cnt, &HTfd_intr)) {
! 289: if (THD_TRACE)
! 290: fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
! 291: found = SOC_INTERRUPT;
! 292: break;
! 293: }
! 294: }
! 295:
! 296: if (found == SOC_INVALID) {
! 297: #ifdef _WINSOCKAPI_
! 298: for (ic = 0; ic < HTfd_set.fd_count; ic++) {
! 299: cnt = HTfd_set.fd_array[ic];
! 300: #else
! 301: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* READ */
! 302: #endif
! 303: if (FD_ISSET(cnt, fd_read)) {
! 304: if (THD_TRACE)
! 305: fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
! 306: found = SOC_READ;
! 307: break;
! 308: }
! 309: }
! 310: }
! 311:
! 312: if (found == SOC_INVALID) {
! 313: #ifdef _WINSOCKAPI_
! 314: for (ic = 0; ic < HTfd_set.fd_count; ic++) {
! 315: cnt = HTfd_set.fd_array[ic];
! 316: #else
! 317: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* WRITE */
! 318: #endif
! 319: if (FD_ISSET(cnt, fd_write)) {
! 320: if (THD_TRACE)
! 321: fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
! 322: found = SOC_WRITE;
! 323: break;
! 324: }
! 325: }
! 326: }
! 327:
! 328: if (found == SOC_INVALID || cur == NULL)
! 329: return NULL;
! 330:
! 331: /* Find the corresponding HTNetInfo and HTRequest structure */
! 332: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
! 333: if (pres->sockfd == cnt) {
! 334: pres->action = found;
! 335: return pres->request;
! 336: }
! 337: }
! 338: return NULL;
! 339: }
! 340:
Webmaster