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