Annotation of libwww/Library/src/HTNet.c, revision 2.4
2.4 ! frystyk 1: /* HTThread.c
! 2: ** MULTIPLE THREAD SOCKET MANAGEMENT
2.1 frystyk 3: **
2.4 ! frystyk 4: ** (c) COPYRIGHT CERN 1994.
! 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:
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: /* Type definitions and global variables etc. local to this module */
24: PRIVATE fd_set HTfd_read; /* Bit array of sockets ready for read */
25: PRIVATE fd_set HTfd_write; /* Bit array of sockets ready for write */
26: PRIVATE int HTMaxfdpl = 0; /* Max number of sockets + 1 */
27:
28: PRIVATE fd_set HTfd_intr; /* All sockets currently interrupted */
29: PRIVATE fd_set HTfd_set; /* All sockets currently registered */
30:
31: PRIVATE HTList *HTThreads = NULL; /* List of the HTNetInfo structures */
32:
33: /* ------------------------------------------------------------------------- */
34:
35: /* HTThreadInit
36: **
37: ** Initiates the thread socket registers. It is very important that
38: ** this function is called. It is currently done inside HTAccess in the
39: ** HTAccessInit function.
40: */
41: PUBLIC BOOL HTThreadInit NOARGS
42: {
43: static BOOL done=NO;
44:
45: if (done) {
46: if (THD_TRACE)
47: fprintf(stderr, "ThreadInit.. Already done\n");
48: return NO;
49: }
50: done = YES;
51:
52: /* Initialize the other internal bit arrays */
53: FD_ZERO(&HTfd_write);
54: FD_ZERO(&HTfd_set);
55: FD_ZERO(&HTfd_intr);
56: return YES;
57: }
58:
59:
60: /* HTThreadGetFDInfo
61: **
62: ** Returns the maximum bit width and the read and write bit array.
63: */
64: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
65: {
66: *read = HTfd_read;
67: *write = HTfd_write;
68: return HTMaxfdpl;
69: }
70:
71:
72: /* HTThreadState
73: **
74: ** This function registers a socket as waiting for the action given
75: ** (read or write etc.).
76: */
77: PUBLIC void HTThreadState ARGS2(int, sockfd, HTThreadAction, action)
78: {
79: if (THD_TRACE) {
80: static char *actionmsg[] = {
81: "SET WRITE",
82: "CLEAR WRITE",
83: "SET READ",
84: "CLEAR READ",
2.4 ! frystyk 85: "SET INTERRUPT",
! 86: "CLEAR INTERRUPT",
2.1 frystyk 87: "CLOSE"
88: };
89: fprintf(stderr,
90: "Thread...... Register socket number %d for action %s\n",
91: sockfd, *(actionmsg+action));
92: }
93: switch (action) {
94: case THD_SET_WRITE:
95: FD_CLR(sockfd, &HTfd_read);
96: FD_SET(sockfd, &HTfd_write);
97: FD_SET(sockfd, &HTfd_set);
98: break;
99:
100: case THD_CLR_WRITE:
101: FD_CLR(sockfd, &HTfd_read);
102: FD_CLR(sockfd, &HTfd_write);
103: FD_CLR(sockfd, &HTfd_set);
104: break;
105:
106: case THD_SET_READ:
107: FD_SET(sockfd, &HTfd_read);
108: FD_CLR(sockfd, &HTfd_write);
109: FD_SET(sockfd, &HTfd_set);
110: break;
111:
112: case THD_CLR_READ:
113: FD_CLR(sockfd, &HTfd_read);
114: FD_CLR(sockfd, &HTfd_write);
115: FD_CLR(sockfd, &HTfd_set);
116: break;
117:
118: case THD_CLOSE:
119: FD_CLR(sockfd, &HTfd_read);
120: FD_CLR(sockfd, &HTfd_write);
2.3 howcome 121: #if 0
2.1 frystyk 122: FD_CLR(sockfd, &HTfd_intr);
2.3 howcome 123: #endif
2.1 frystyk 124: FD_CLR(sockfd, &HTfd_set);
125: break;
126:
2.2 frystyk 127: case THD_SET_INTR:
2.1 frystyk 128: FD_CLR(sockfd, &HTfd_read);
129: FD_CLR(sockfd, &HTfd_write);
130: FD_SET(sockfd, &HTfd_intr);
131: break;
132:
2.2 frystyk 133: case THD_CLR_INTR:
134: FD_CLR(sockfd, &HTfd_intr);
135: break;
136:
2.1 frystyk 137: default:
138: if (THD_TRACE)
139: fprintf(stderr, "Thread...... Illigal socket action\n");
140: }
141:
142: /* Update max bit width. The method used ignores any other default
2.2 frystyk 143: opened file descriptors between 0 and the actual set of file
144: descriptors used. However, they are not registered anyway */
2.1 frystyk 145: if (action == THD_CLOSE) {
146: if (sockfd+1 >= HTMaxfdpl) {
2.2 frystyk 147: while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
2.1 frystyk 148: HTMaxfdpl--;
149: }
150: } else {
151: if (sockfd+1 > HTMaxfdpl)
152: HTMaxfdpl = sockfd+1;
153: }
154: if (THD_TRACE)
155: fprintf(stderr, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
156: }
157:
158:
159: /* HTThreadIntr
160: **
161: ** This function returns YES or NO to the question
162: */
163: PUBLIC BOOL HTThreadIntr ARGS1(int, sockfd)
164: {
165: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
166: }
167:
168:
169: /* HTThreadMarkIntrAll
170: **
2.2 frystyk 171: ** Marks all Library sockets as interrupted. User sockets can not be
172: ** interrupted
2.1 frystyk 173: */
2.2 frystyk 174: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *, fd_user)
2.1 frystyk 175: {
176: int cnt;
177: if (THD_TRACE)
2.2 frystyk 178: fprintf(stderr, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
179: for (cnt=0; cnt<HTMaxfdpl; cnt++) {
2.4 ! frystyk 180: if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
! 181: FD_SET(cnt, &HTfd_intr);
2.2 frystyk 182: }
2.1 frystyk 183: }
184:
185:
186: /* HTThreadActive
187: **
188: ** Returns yes as long as a socket other than stdin is registered in
189: ** the total set of sockets.
190: */
191: PUBLIC BOOL HTThreadActive NOARGS
192: {
193: int cnt;
194: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
195: if (FD_ISSET(cnt, &HTfd_set))
196: return YES;
197: return NO;
198: }
199:
200:
201: /* HTThread_new
202: **
203: ** Register the HTNetInfo structure in a list so that we can find the
204: ** request which corresponds to a socket descriptor
205: */
206: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
207: {
208: if (!HTThreads)
209: HTThreads = HTList_new();
210: HTList_addObject(HTThreads, (void *) new_net);
211: }
212:
213:
214: /* HTThread_clear
215: **
216: ** Remove the HTNetInfo from the list of acrive threads.
217: */
218: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
219: {
220: if (HTThreads)
221: return HTList_removeObject(HTThreads, (void *) old_net);
222: return NO;
223: }
224:
225:
226: /* HTThread_getCallBack
227: **
228: ** Finds a socket and makes it the active thread. READ has a higher
229: ** priority than WRITE as it might influence (stop) the WRITE process.
230: ** Returns the request structure of the active thread, NULL on error.
231: ** A interrupted socket has the highest priority
232: */
233: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *, fd_read,
234: CONST fd_set *, fd_write)
235: {
236: HTList *cur = HTThreads;
237: HTNetInfo *pres;
238: int cnt;
239: BOOL found = NO;
240: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
241: if (FD_ISSET(cnt, &HTfd_intr)) {
242: if (THD_TRACE)
243: fprintf(stderr, "GetSocket... Socket %d INTERRUPTED\n", cnt);
244: found = YES;
245: break;
246: }
247: }
248: if (!found) {
249: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* READ */
250: if (FD_ISSET(cnt, fd_read)) {
251: if (THD_TRACE)
252: fprintf(stderr, "GetSocket... Socket %d for READ\n", cnt);
253: found = YES;
254: break;
255: }
256: }
257: }
258: if (!found) {
259: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* WRITE */
260: if (FD_ISSET(cnt, fd_write)) {
261: if (THD_TRACE)
262: fprintf(stderr, "GetSocket... Socket %d for WRITE\n", cnt);
263: found = YES;
264: break;
265: }
266: }
267: }
268: if (!found || cur == NULL)
269: return NULL;
270:
271: /* Find the corresponding HTNetInfo structure */
272: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
273: if (pres->sockfd == cnt) {
274: return pres->request;
275: }
276: }
277: return NULL;
278: }
Webmaster