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