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