Added a better SCAN.
[yaz-moved-to-github.git] / server / eventl.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: eventl.c,v $
7  * Revision 1.9  1995-06-05 10:53:31  quinn
8  * Added a better SCAN.
9  *
10  * Revision 1.8  1995/05/16  08:51:01  quinn
11  * License, documentation, and memory fixes
12  *
13  * Revision 1.7  1995/03/27  15:02:01  quinn
14  * Added some includes for better portability
15  *
16  * Revision 1.6  1995/03/27  08:34:21  quinn
17  * Added dynamic server functionality.
18  * Released bindings to session.c (is now redundant)
19  *
20  * Revision 1.5  1995/03/15  08:37:41  quinn
21  * Now we're pretty much set for nonblocking I/O.
22  *
23  * Revision 1.4  1995/03/14  16:59:48  quinn
24  * Bug-fixes
25  *
26  * Revision 1.3  1995/03/14  11:30:14  quinn
27  * Works better now.
28  *
29  * Revision 1.2  1995/03/14  10:27:59  quinn
30  * More work on demo server.
31  *
32  * Revision 1.1  1995/03/10  18:22:44  quinn
33  * The rudiments of an asynchronous server.
34  *
35  */
36
37 #include <assert.h>
38 #include <sys/time.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <string.h>
44 #ifdef _AIX
45 #include <sys/select.h>
46 #endif
47
48 #include <eventl.h>
49
50 #include <dmalloc.h>
51
52 static IOCHAN iochans = 0;
53
54 IOCHAN iochan_getchan(void)
55 {
56     return iochans;
57 }
58
59 IOCHAN iochan_create(int fd, IOC_CALLBACK cb, int flags)
60 {
61     IOCHAN new;
62
63     if (!(new = malloc(sizeof(*new))))
64         return 0;
65     new->destroyed = 0;
66     new->fd = fd;
67     new->flags = flags;
68     new->fun = cb;
69     new->next = iochans;
70     new->force_event = 0;
71     iochans = new;
72     return new;
73 }
74
75 int event_loop()
76 {
77     do
78     {
79         IOCHAN p, nextp;
80         fd_set in, out, except;
81         int res, max;
82         static struct timeval nullto = {0, 0};
83         struct timeval *timeout;
84
85         FD_ZERO(&in);
86         FD_ZERO(&out);
87         FD_ZERO(&except);
88         timeout = 0; /* hang on select */
89         max = 0;
90         for (p = iochans; p; p = p->next)
91         {
92             if (p->force_event)
93                 timeout = &nullto;
94             if (p->flags & EVENT_INPUT)
95                 FD_SET(p->fd, &in);
96             if (p->flags & EVENT_OUTPUT)
97                 FD_SET(p->fd, &out);
98             if (p->flags & EVENT_EXCEPT)
99                 FD_SET(p->fd, &except);
100             if (p->fd > max)
101                 max = p->fd;
102         }
103         if ((res = select(max + 1, &in, &out, &except, timeout)) < 0)
104         {
105             if (errno == EINTR)
106                 continue;
107             return 1;
108         }
109         for (p = iochans; p; p = p->next)
110         {
111             int force_event = p->force_event;
112
113             p->force_event = 0;
114             if (FD_ISSET(p->fd, &in) || force_event == EVENT_INPUT)
115                 (*p->fun)(p, EVENT_INPUT);
116             if (!p->destroyed && (FD_ISSET(p->fd, &out) ||
117                  force_event == EVENT_OUTPUT))
118                 (*p->fun)(p, EVENT_OUTPUT);
119             if (!p->destroyed && (FD_ISSET(p->fd, &except) ||
120                 force_event == EVENT_EXCEPT))
121                 (*p->fun)(p, EVENT_EXCEPT);
122         }
123         for (p = iochans; p; p = nextp)
124         {
125             nextp = p->next;
126
127             if (p->destroyed)
128             {
129                 IOCHAN tmp = p, pr;
130
131                 if (p == iochans)
132                     iochans = p->next;
133                 else
134                 {
135                     for (pr = iochans; pr; pr = pr->next)
136                         if (pr->next == p)
137                             break;
138                     assert(pr);
139                     pr->next = p->next;
140                 }
141                 if (nextp == p)
142                     nextp = p->next;
143                 free(tmp);
144             }
145         }
146     }
147     while (iochans);
148     return 0;
149 }