2 #include <yaz/sock_man.h>
9 struct yaz_sock_man_s {
10 yaz_sock_chan_t chan_list;
11 yaz_sock_chan_t free_list;
12 yaz_sock_chan_t timeout_list;
20 struct epoll_event *events;
23 struct yaz_sock_chan_s {
34 yaz_sock_man_t yaz_sock_man_new(void)
36 NMEM nmem = nmem_create();
37 yaz_sock_man_t man = nmem_malloc(nmem, sizeof(*man));
41 man->timeout_list = 0;
42 man->epoll_handle = epoll_create(100);
48 man->events = nmem_malloc(nmem, man->maxevents * sizeof(*man->events));
49 if (man->epoll_handle == -1)
51 yaz_sock_man_destroy(man);
57 void yaz_sock_man_destroy(yaz_sock_man_t man)
61 while (man->chan_list)
63 yaz_log(YLOG_WARN, "yaz_sock_man_destroy: closing %p",
65 yaz_sock_chan_destroy(man->chan_list);
67 if (man->epoll_handle != -1)
68 close(man->epoll_handle);
69 nmem_destroy(man->nmem);
73 static void poll_ctl(int op, yaz_sock_chan_t p)
75 struct epoll_event event;
78 if (p->input_mask & yaz_poll_read)
79 event.events |= EPOLLIN;
80 if (p->input_mask & yaz_poll_write)
81 event.events |= EPOLLOUT;
82 if (p->input_mask & yaz_poll_except)
83 event.events |= EPOLLERR;
86 epoll_ctl(p->man->epoll_handle, op, p->fd, &event);
90 yaz_sock_chan_t yaz_sock_chan_new(yaz_sock_man_t srv, int fd, void *data,
97 srv->free_list = p->next;
100 p = nmem_malloc(srv->nmem, sizeof(*p));
101 p->next = srv->chan_list;
108 p->input_mask = mask;
114 poll_ctl(EPOLL_CTL_ADD, p);
118 static void rescan_timeout(yaz_sock_man_t man)
124 for (p = man->chan_list; p; p = p->next)
125 if (p->max_idle != -1 && (timeout == -1 || p->max_idle < timeout))
126 timeout = p->max_idle;
127 man->timeout = timeout;
132 void yaz_sock_chan_destroy(yaz_sock_chan_t p)
134 yaz_sock_man_t srv = p->man;
136 p->prev->next = p->next;
139 assert(srv->chan_list == p);
140 srv->chan_list = p->next;
144 p->next->prev = p->prev;
146 poll_ctl(EPOLL_CTL_DEL, p);
148 p->next = srv->free_list;
155 yaz_sock_chan_t yaz_sock_man_wait(yaz_sock_man_t man)
157 struct epoll_event *ev;
158 yaz_sock_chan_t chan = 0;
160 if (man->timeout_list)
161 { /* possibly timeout events not returned */
162 for (chan = man->timeout_list; chan; chan = chan->next)
163 if (chan->max_idle == man->timeout)
167 man->timeout_list = chan->next;
168 chan->output_mask = yaz_poll_timeout;
171 man->timeout_list = 0; /* no more timeout events */
173 assert(man->timeout_list == 0);
174 assert(man->event_no <= man->event_ret);
175 if (man->event_no == man->event_ret)
176 { /* must wait again */
179 man->event_ret = epoll_wait(man->epoll_handle, man->events,
180 man->maxevents, man->timeout);
181 if (man->event_ret == 0)
184 for (chan = man->chan_list; chan; chan = chan->next)
185 if (chan->max_idle == man->timeout)
187 assert(chan); /* there must be one chan in a timeout state */
188 man->timeout_list = chan->next;
189 chan->output_mask = yaz_poll_timeout;
192 else if (man->event_ret < 0)
198 ev = man->events + man->event_no;
200 chan->output_mask = 0;
201 if (ev->events & EPOLLIN)
202 chan->output_mask |= yaz_poll_read;
203 if (ev->events & EPOLLOUT)
204 chan->output_mask |= yaz_poll_write;
205 if (ev->events & EPOLLERR)
206 chan->output_mask |= yaz_poll_except;
211 void yaz_sock_chan_set_mask(yaz_sock_chan_t chan, unsigned mask)
213 if (chan->input_mask != mask)
215 chan->input_mask = mask;
216 poll_ctl(EPOLL_CTL_MOD, chan);
220 void yaz_sock_chan_set_max_idle(yaz_sock_chan_t chan, int max_idle)
222 if (chan->max_idle != max_idle)
224 chan->max_idle = max_idle;
225 chan->man->rescan = 1;
229 unsigned yaz_sock_get_mask(yaz_sock_chan_t chan)
231 return chan->output_mask;
234 void *yaz_sock_chan_get_data(yaz_sock_chan_t chan)
243 * c-file-style: "Stroustrup"
244 * indent-tabs-mode: nil
246 * vim: shiftwidth=4 tabstop=8 expandtab