2 #include <yaz/sock_man.h>
8 struct yaz_sock_man_s {
9 yaz_sock_chan_t chan_list;
10 yaz_sock_chan_t free_list;
11 yaz_sock_chan_t timeout_list;
19 struct epoll_event *events;
22 struct yaz_sock_chan_s {
33 yaz_sock_man_t yaz_sock_man_new(void)
35 NMEM nmem = nmem_create();
36 yaz_sock_man_t man = nmem_malloc(nmem, sizeof(*man));
40 man->timeout_list = 0;
41 man->epoll_handle = epoll_create(100);
47 man->events = nmem_malloc(nmem, man->maxevents * sizeof(*man->events));
48 if (man->epoll_handle == -1)
50 yaz_sock_man_destroy(man);
56 void yaz_sock_man_destroy(yaz_sock_man_t man)
60 if (man->epoll_handle != -1)
61 close(man->epoll_handle);
62 assert(man->chan_list == 0);
63 nmem_destroy(man->nmem);
67 static void poll_ctl(int op, yaz_sock_chan_t p)
69 struct epoll_event event;
72 if (p->mask & yaz_poll_read)
73 event.events |= EPOLLIN;
74 if (p->mask & yaz_poll_write)
75 event.events |= EPOLLOUT;
76 if (p->mask & yaz_poll_except)
77 event.events |= EPOLLERR;
80 epoll_ctl(p->man->epoll_handle, op, p->fd, &event);
84 yaz_sock_chan_t yaz_sock_chan_new(yaz_sock_man_t srv, int fd, void *data,
91 srv->free_list = p->next;
94 p = nmem_malloc(srv->nmem, sizeof(*p));
95 p->next = srv->chan_list;
107 poll_ctl(EPOLL_CTL_ADD, p);
111 static void rescan_timeout(yaz_sock_man_t man)
117 for (p = man->chan_list; p; p = p->next)
118 if (p->max_idle && (timeout == 0 || p->max_idle < timeout))
119 timeout = p->max_idle;
120 man->timeout = timeout;
125 void yaz_sock_chan_destroy(yaz_sock_man_t srv, yaz_sock_chan_t p)
128 p->prev->next = p->next;
131 assert(srv->chan_list == p);
132 srv->chan_list = p->next;
136 p->next->prev = p->prev;
138 poll_ctl(EPOLL_CTL_DEL, p);
140 p->next = srv->free_list;
147 yaz_sock_chan_t yaz_sock_man_wait(yaz_sock_man_t man)
149 struct epoll_event *ev;
150 yaz_sock_chan_t chan = 0;
152 if (man->timeout_list)
153 { /* possibly timeout events not returned */
154 for (chan = man->timeout_list; chan; chan = chan->next)
155 if (chan->max_idle == man->timeout)
159 man->timeout_list = chan->next;
160 chan->output_mask = yaz_poll_timeout;
163 man->timeout_list = 0; /* no more timeout events */
165 assert(man->timeout_list = 0);
166 assert(man->event_no <= man->event_ret);
167 if (man->event_no == man->event_ret)
168 { /* must wait again */
171 man->event_ret = epoll_wait(man->epoll_handle, man->events,
172 man->maxevents, man->timeout);
173 if (man->event_ret == 0)
176 for (chan = man->chan_list; chan; chan = chan->next)
177 if (chan->max_idle == man->timeout)
179 assert(chan); /* there must be one chan in a timeout state */
180 man->timeout_list = chan->next;
181 chan->output_mask = yaz_poll_timeout;
184 else if (man->event_ret < 0)
190 ev = man->events + man->event_no;
192 chan->output_mask = 0;
193 if (ev->events & EPOLLIN)
194 chan->output_mask |= yaz_poll_read;
195 if (ev->events & EPOLLOUT)
196 chan->output_mask |= yaz_poll_write;
197 if (ev->events & EPOLLERR)
198 chan->output_mask |= yaz_poll_except;
203 void yaz_sock_chan_set_mask(yaz_sock_chan_t chan, unsigned mask)
205 if (chan->mask != mask)
208 poll_ctl(EPOLL_CTL_MOD, chan);
212 void yaz_sock_chan_set_max_idle(yaz_sock_chan_t chan, int max_idle)
214 if (chan->max_idle != max_idle)
216 chan->max_idle = max_idle;
217 chan->man->rescan = 1;
221 unsigned yaz_sock_get_mask(yaz_sock_chan_t chan)
226 void *yaz_sock_chan_get_data(yaz_sock_chan_t chan)
235 * c-file-style: "Stroustrup"
236 * indent-tabs-mode: nil
238 * vim: shiftwidth=4 tabstop=8 expandtab