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