Annotation of libwww/Library/src/HTNet.c, revision 2.16.2.1
2.4 frystyk 1: /* HTThread.c
2: ** MULTIPLE THREAD SOCKET MANAGEMENT
2.1 frystyk 3: **
2.10 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.4 frystyk 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:
2.14 frystyk 11: ** 12 June 94 Written by Henrik Frystyk, frystyk@w3.org
2.16.2.1! frystyk 12: ** 31 May 95 Charlie Brooks cbrooks@osf.org
! 13: **
2.1 frystyk 14: */
15:
2.9 frystyk 16: /* Implemention dependent include files */
17: #include "tcp.h"
18:
2.1 frystyk 19: /* Library include files */
20: #include "HTUtils.h"
21: #include "HTAccess.h"
2.16 frystyk 22: #include "HTProt.h"
2.1 frystyk 23: #include "HTError.h"
24: #include "HTThread.h" /* Implemented here */
2.16.2.1! frystyk 25: #include "HTEvntrg.h"
2.1 frystyk 26:
2.9 frystyk 27: #ifdef WIN32
28: #include <io.h>
29: #endif
30:
2.1 frystyk 31:
2.16.2.1! frystyk 32: PRIVATE HTList *HTThreads = NULL; /* List of the HTNetInfo structures */
! 33: PRIVATE fd_set nullSet ;
! 34: PRIVATE fd_set HTfd_intr;
! 35: PRIVATE fd_set HTfd_libs ;
! 36: PRIVATE SOCKET libMaxSock = 0 ;
2.1 frystyk 37:
2.9 frystyk 38:
2.16.2.1! frystyk 39: int LibraryCallback( SOCKET, HTRequest *, SockOps) ;
2.1 frystyk 40:
41: /* ------------------------------------------------------------------------- */
42:
43: /* HTThreadInit
44: **
45: ** Initiates the thread socket registers. It is very important that
46: ** this function is called. It is currently done inside HTAccess in the
47: ** HTAccessInit function.
48: */
49: PUBLIC BOOL HTThreadInit NOARGS
50: {
51: static BOOL done=NO;
52:
53: if (done) {
54: if (THD_TRACE)
2.7 frystyk 55: fprintf(TDEST, "ThreadInit.. Already done\n");
2.1 frystyk 56: return NO;
57: }
58: done = YES;
2.16.2.1! frystyk 59: FD_ZERO( &HTfd_intr) ;
2.1 frystyk 60: return YES;
61: }
62:
63:
64: /* HTThreadGetFDInfo
65: **
66: ** Returns the maximum bit width and the read and write bit array.
2.16.2.1! frystyk 67: ** N.B. Only used by old HTEvent.c module
2.1 frystyk 68: */
2.16.2.1! frystyk 69:
2.1 frystyk 70: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
71: {
2.16.2.1! frystyk 72: *read = nullSet;
! 73: *write = nullSet;
! 74: return libMaxSock;
2.1 frystyk 75: }
76:
2.15 frystyk 77: /* HTThreadStateByRequest
78: **
79: ** This function registers a socket as waiting for the action given
80: ** (read or write etc.). It uses the request structure to find the socket
81: */
82: PUBLIC void HTThreadStateByRequest ARGS2(HTRequest *, request,
83: HTThreadAction, action)
84: {
85: if (request && request->net_info && request->net_info->sockfd != INVSOC)
86: HTThreadState(request->net_info->sockfd, action);
87: }
88:
2.16.2.1! frystyk 89:
! 90:
2.1 frystyk 91: /* HTThreadState
92: **
93: ** This function registers a socket as waiting for the action given
94: ** (read or write etc.).
2.16.2.1! frystyk 95: **
! 96: ** Charlie Brooks - we handle the interrupt thread state internally to this module
! 97: ** setting the interrupt on a socket disables it from read/write.
2.1 frystyk 98: */
2.7 frystyk 99: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
2.1 frystyk 100: {
2.16.2.1! frystyk 101: register HTNetInfo * pres ;
! 102: HTList * cur = HTThreads ;
! 103: int found = 0 ;
! 104: HTRequest * reqst ;
! 105:
2.9 frystyk 106: #ifdef _WIN32
2.16.2.1! frystyk 107: if (sockfd <= 2)
! 108: sockfd = _get_osfhandle(sockfd) ;
2.9 frystyk 109: #endif
110:
2.1 frystyk 111: if (THD_TRACE) {
112: static char *actionmsg[] = {
113: "SET WRITE",
114: "CLEAR WRITE",
115: "SET READ",
116: "CLEAR READ",
2.4 frystyk 117: "SET INTERRUPT",
118: "CLEAR INTERRUPT",
2.16.2.1! frystyk 119: "CLOSE",
! 120: "SET CONNECT",
! 121: "CLEAR CONNECT"
2.1 frystyk 122: };
2.7 frystyk 123: fprintf(TDEST,
2.16.2.1! frystyk 124: "Thread...... Registering socket number %d for action %s\n",
2.1 frystyk 125: sockfd, *(actionmsg+action));
2.16.2.1! frystyk 126: } /* if */
! 127:
! 128: FD_SET( sockfd, &HTfd_libs) ;
! 129: if (libMaxSock < sockfd)
! 130: libMaxSock = sockfd ;
! 131:
! 132:
! 133: while ((pres = (HTNetInfo *)HTList_nextObject(cur) ) != 0) {
! 134: if (pres->sockfd == sockfd) {
! 135: found = 1 ;
! 136: break ;
! 137: } /* if */
! 138: } /* while */
! 139:
! 140: if (! found) /* how'd you get here? */
! 141: return ;
! 142:
! 143: reqst = pres->request ;
2.1 frystyk 144: switch (action) {
145: case THD_SET_WRITE:
2.16.2.1! frystyk 146: case THD_SET_CONNECT:
! 147: HTEvent_Register( sockfd, reqst, action == THD_SET_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT ,
! 148: LibraryCallback, 0);
2.1 frystyk 149: break;
150:
151: case THD_CLR_WRITE:
2.16.2.1! frystyk 152: case THD_CLR_CONNECT:
! 153: HTEvent_UnRegister( sockfd, action == THD_CLR_WRITE ? (SockOps)FD_WRITE : (SockOps)FD_CONNECT) ;
2.1 frystyk 154: break;
155:
156: case THD_SET_READ:
2.16.2.1! frystyk 157: HTEvent_Register( sockfd, reqst, (SockOps)FD_READ, LibraryCallback, 0);
2.1 frystyk 158: break;
159:
160: case THD_CLR_READ:
2.16.2.1! frystyk 161: HTEvent_UnRegister( sockfd, FD_WRITE) ;
2.1 frystyk 162: break;
163:
164: case THD_CLOSE:
2.16.2.1! frystyk 165: HTEvent_UnRegister( sockfd, FD_ALL) ;
! 166: FD_CLR( sockfd, &HTfd_libs);
! 167: FD_CLR( sockfd, &HTfd_intr);
! 168: libMaxSock = 0 ;
! 169: while ((pres = (HTNetInfo *)HTList_nextObject(cur) ) != 0) {
! 170: if (pres->sockfd > libMaxSock) {
! 171: libMaxSock = sockfd ;
! 172: } /* if */
! 173: } /* while */
! 174:
2.1 frystyk 175: break;
176:
2.16.2.1! frystyk 177: /*
! 178: * we handle interrupts locally ... only library sockets can
! 179: * be interrupted?
! 180: */
! 181:
2.2 frystyk 182: case THD_SET_INTR:
2.16.2.1! frystyk 183: HTEvent_UnRegister( sockfd, (SockOps)(FD_READ | FD_WRITE) );
! 184: FD_SET( sockfd, &HTfd_intr) ;
2.1 frystyk 185: break;
186:
2.2 frystyk 187: case THD_CLR_INTR:
2.16.2.1! frystyk 188: FD_CLR( sockfd, &HTfd_intr) ;
! 189: HTEvent_UnRegister(sockfd, FD_ALL) ; /* no sin to unregister and unregistered socket */
2.2 frystyk 190: break;
191:
2.1 frystyk 192: default:
193: if (THD_TRACE)
2.16.2.1! frystyk 194: fprintf(TDEST, "Thread...... Illegal socket action (%d)\n", (int)action);
2.1 frystyk 195: }
2.16.2.1! frystyk 196: return ;
2.1 frystyk 197: }
198:
199:
200: /* HTThreadIntr
201: **
202: ** This function returns YES or NO to the question
203: */
2.7 frystyk 204: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
2.1 frystyk 205: {
206: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
207: }
208:
209:
210: /* HTThreadMarkIntrAll
211: **
2.2 frystyk 212: ** Marks all Library sockets as interrupted. User sockets can not be
2.16.2.1! frystyk 213: ** interrupted
2.1 frystyk 214: */
2.16.2.1! frystyk 215: PUBLIC BOOL HTThreadMarkIntrAll( CONST fd_set * fd_user )
2.1 frystyk 216: {
2.12 frystyk 217: HTNetInfo *pres;
218: if (HTThreads) {
219: while ((pres = (HTNetInfo *) HTList_lastObject(HTThreads)) != NULL)
220: HTThread_kill(pres);
221: return YES;
222: }
223: return NO;
224:
2.1 frystyk 225: }
226:
227:
228: /* HTThreadActive
229: **
230: ** Returns yes as long as a socket other than stdin is registered in
231: ** the total set of sockets.
232: */
233: PUBLIC BOOL HTThreadActive NOARGS
234: {
2.16.2.1! frystyk 235: if (libMaxSock > 0)
! 236: return YES;
! 237: else
! 238: return NO;
2.1 frystyk 239: }
240:
241:
242: /* HTThread_new
243: **
244: ** Register the HTNetInfo structure in a list so that we can find the
2.16.2.1! frystyk 245: ** request which corresponds to a socket descriptor
2.1 frystyk 246: */
2.12 frystyk 247: PUBLIC BOOL HTThread_new ARGS1(HTNetInfo *, new_net)
2.1 frystyk 248: {
249: if (!HTThreads)
2.16.2.1! frystyk 250: HTThreads = HTList_new();
2.12 frystyk 251: return HTList_addObject(HTThreads, (void *) new_net);
2.1 frystyk 252: }
253:
254:
255: /* HTThread_clear
256: **
2.16.2.1! frystyk 257: ** Remove the HTNetInfo from the list of acrive threads.
2.1 frystyk 258: */
2.12 frystyk 259: PUBLIC BOOL HTThread_clear ARGS1(HTNetInfo *, old_net)
2.1 frystyk 260: {
261: if (HTThreads)
262: return HTList_removeObject(HTThreads, (void *) old_net);
263: return NO;
264: }
265:
2.16.2.1! frystyk 266: /* HTThread_isAlive
! 267: **
! 268: ** Checks whether a thread is still registered and if so returns the
! 269: ** corresponding HTRequest structure, else return NULL.
! 270: */
! 271: PUBLIC HTRequest *HTThread_isAlive ARGS1(HTNetInfo *, net)
! 272: {
! 273: HTList *cur = HTThreads;
! 274: HTNetInfo *pres;
! 275: if (cur && net) {
! 276: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
! 277: if (pres == net) return pres->request;
! 278: }
! 279: }
! 280: if (THD_TRACE)
! 281: fprintf(TDEST, "Thread...... Thread is not alive\n");
! 282: return NULL;
! 283: }
! 284:
! 285:
! 286: /*
! 287: * LibraryCallback - "glue" between 3.0 thread code and new callback functions
! 288: * map return codes into a simple yes/no model.
! 289: */
! 290:
! 291: int LibraryCallback( SOCKET s, HTRequest * rq, SockOps f)
! 292: {
! 293: int status = 0 ;
! 294: HTEventState state ;
! 295: HTProtocol * proto = (HTProtocol *)
! 296: HTAnchor_protocol( rq -> anchor) ;
! 297:
! 298: /* begin */
! 299:
! 300: if (proto == 0) /* Whoa! No protocol! */
! 301: return -1;
! 302: status = proto->load( rq ) ;
! 303: if (status != HT_WOULD_BLOCK) { /* completed - good or bad... */
! 304: if (THD_TRACE)
! 305: fprintf(TDEST, "LibCallBack. Calling Terminate...\n");
! 306:
! 307: HTLoadTerminate( rq, status ) ;
! 308: state = HTEventRequestTerminate( rq, status) ;
! 309: /* if the state isn't EVENT_QUIT */
! 310: if (! HTEventCheckState( rq, state ))
! 311: return HT_OK; /* treat as failure */
! 312: } /* if status */
! 313: return HT_WOULD_BLOCK;
! 314: }
2.1 frystyk 315:
2.12 frystyk 316: /* HTThread_kill
317: **
318: ** Kill the thread and remove the HTNetInfo from the list of active
319: ** threads.
320: ** Returns YES on success, NO on error
321: **
322: ** BUG: We do not take ANSI C file descriptors into account
323: */
2.16.2.1! frystyk 324:
2.12 frystyk 325: PUBLIC BOOL HTThread_kill ARGS1(HTNetInfo *, kill_net)
326: {
2.16.2.1! frystyk 327: if (HTThreads) {
2.12 frystyk 328: HTList *cur = HTThreads;
329: HTNetInfo *pres;
330:
331: /* Find the corresponding HTRequest structure */
332: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
333: if (pres == kill_net) break;
334: }
335:
336: /*
337: ** Now see if a socket is active (or an ANSI C file descriptor).
338: ** If so then mark the thread as interrupted and call the load
339: ** function.
340: */
341: if (pres) {
342: if (kill_net->sockfd != INVSOC) { /* @@@ ANSI C FIlE DES @@@ */
343: HTProtocol *prot = (HTProtocol *)
344: HTAnchor_protocol(kill_net->request->anchor);
345: HTThreadState(kill_net->sockfd, THD_SET_INTR);
346: (*(prot->load))(kill_net->request);
347: }
348: return HTThread_clear(kill_net);
2.16.2.1! frystyk 349: } else {
2.1 frystyk 350: if (THD_TRACE)
2.16.2.1! frystyk 351: fprintf(TDEST, "Kill Thread. Thread is not registered\n");
! 352: return NO;
2.1 frystyk 353: }
354: }
2.16.2.1! frystyk 355: return NO;
2.1 frystyk 356: }
Webmaster