Annotation of libwww/Library/src/HTNet.c, revision 2.5
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);
121: FD_CLR(sockfd, &HTfd_intr);
122: FD_CLR(sockfd, &HTfd_set);
123: break;
124:
2.2 frystyk 125: case THD_SET_INTR:
2.1 frystyk 126: FD_CLR(sockfd, &HTfd_read);
127: FD_CLR(sockfd, &HTfd_write);
128: FD_SET(sockfd, &HTfd_intr);
129: break;
130:
2.2 frystyk 131: case THD_CLR_INTR:
132: FD_CLR(sockfd, &HTfd_intr);
133: break;
134:
2.1 frystyk 135: default:
136: if (THD_TRACE)
137: fprintf(stderr, "Thread...... Illigal socket action\n");
138: }
139:
140: /* Update max bit width. The method used ignores any other default
2.2 frystyk 141: opened file descriptors between 0 and the actual set of file
142: descriptors used. However, they are not registered anyway */
2.1 frystyk 143: if (action == THD_CLOSE) {
144: if (sockfd+1 >= HTMaxfdpl) {
2.2 frystyk 145: while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
2.1 frystyk 146: HTMaxfdpl--;
147: }
148: } else {
149: if (sockfd+1 > HTMaxfdpl)
150: HTMaxfdpl = sockfd+1;
151: }
152: if (THD_TRACE)
153: fprintf(stderr, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
154: }
155:
156:
157: /* HTThreadIntr
158: **
159: ** This function returns YES or NO to the question
160: */
161: PUBLIC BOOL HTThreadIntr ARGS1(int, sockfd)
162: {
163: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
164: }
165:
166:
167: /* HTThreadMarkIntrAll
168: **
2.2 frystyk 169: ** Marks all Library sockets as interrupted. User sockets can not be
170: ** interrupted
2.1 frystyk 171: */
2.2 frystyk 172: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *, fd_user)
2.1 frystyk 173: {
174: int cnt;
175: if (THD_TRACE)
2.2 frystyk 176: fprintf(stderr, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
177: for (cnt=0; cnt<HTMaxfdpl; cnt++) {
2.4 frystyk 178: if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
179: FD_SET(cnt, &HTfd_intr);
2.2 frystyk 180: }
2.1 frystyk 181: }
182:
183:
184: /* HTThreadActive
185: **
186: ** Returns yes as long as a socket other than stdin is registered in
187: ** the total set of sockets.
188: */
189: PUBLIC BOOL HTThreadActive NOARGS
190: {
191: int cnt;
192: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
193: if (FD_ISSET(cnt, &HTfd_set))
194: return YES;
195: return NO;
196: }
197:
198:
199: /* HTThread_new
200: **
201: ** Register the HTNetInfo structure in a list so that we can find the
202: ** request which corresponds to a socket descriptor
203: */
204: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
205: {
206: if (!HTThreads)
207: HTThreads = HTList_new();
208: HTList_addObject(HTThreads, (void *) new_net);
209: }
210:
211:
212: /* HTThread_clear
213: **
214: ** Remove the HTNetInfo from the list of acrive threads.
215: */
216: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
217: {
218: if (HTThreads)
219: return HTList_removeObject(HTThreads, (void *) old_net);
220: return NO;
221: }
222:
223:
224: /* HTThread_getCallBack
225: **
226: ** Finds a socket and makes it the active thread. READ has a higher
227: ** priority than WRITE as it might influence (stop) the WRITE process.
228: ** Returns the request structure of the active thread, NULL on error.
229: ** A interrupted socket has the highest priority
230: */
231: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *, fd_read,
232: CONST fd_set *, fd_write)
233: {
234: HTList *cur = HTThreads;
235: HTNetInfo *pres;
236: int cnt;
237: BOOL found = NO;
238: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
239: if (FD_ISSET(cnt, &HTfd_intr)) {
240: if (THD_TRACE)
241: fprintf(stderr, "GetSocket... Socket %d INTERRUPTED\n", cnt);
242: found = YES;
243: break;
244: }
245: }
246: if (!found) {
247: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* READ */
248: if (FD_ISSET(cnt, fd_read)) {
249: if (THD_TRACE)
250: fprintf(stderr, "GetSocket... Socket %d for READ\n", cnt);
251: found = YES;
252: break;
253: }
254: }
255: }
256: if (!found) {
257: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* WRITE */
258: if (FD_ISSET(cnt, fd_write)) {
259: if (THD_TRACE)
260: fprintf(stderr, "GetSocket... Socket %d for WRITE\n", cnt);
261: found = YES;
262: break;
263: }
264: }
265: }
266: if (!found || cur == NULL)
267: return NULL;
268:
269: /* Find the corresponding HTNetInfo structure */
270: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
271: if (pres->sockfd == cnt) {
272: return pres->request;
273: }
274: }
275: return NULL;
276: }
Webmaster