void iochan_handler(struct iochan *i, int event) { sel_thread_t p = iochan_getdata(i); if (event & EVENT_INPUT) { struct work *w = sel_thread_result(p); w->host->ipport = w->ipport; connect_resolver_host(w->host, w->iochan_man); xfree(w); } }
void iochan_handler(struct iochan *i, int event) { static int number = 0; sel_thread_t p = iochan_getdata(i); if (event & EVENT_INPUT) { struct my_work_data *work; work = sel_thread_result(p); YAZ_CHECK(work); if (work) { YAZ_CHECK_EQ(work->x * 2, work->y); /* stop work after a couple of iterations */ if (work->x > 10) iochan_destroy(i); xfree(work); } } if (event & EVENT_TIMEOUT) { struct my_work_data *work; work = xmalloc(sizeof(*work)); work->x = number; sel_thread_add(p, work); work = xmalloc(sizeof(*work)); work->x = number+1; sel_thread_add(p, work); number += 10; } }
static int event_loop(iochan_man_t man, IOCHAN *iochans) { do /* loop as long as there are active associations to process */ { IOCHAN p, *nextp; IOCHAN start; IOCHAN inv_start; fd_set in, out, except; int res, max; static struct timeval to; struct timeval *timeout; // struct yaz_poll_fd *fds; int no_fds = 0; FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&except); timeout = &to; /* hang on select */ to.tv_sec = 300; to.tv_usec = 0; // INV: start must no change through the loop yaz_mutex_enter(man->iochan_mutex); start = man->channel_list; yaz_mutex_leave(man->iochan_mutex); inv_start = start; for (p = start; p; p = p->next) { no_fds++; } // fds = (struct yaz_poll_fd *) xmalloc(no_fds * sizeof(*fds)); max = 0; for (p = start; p; p = p->next) { if (p->thread_users > 0) continue; if (p->max_idle && p->max_idle < to.tv_sec) to.tv_sec = p->max_idle; if (p->fd < 0) continue; if (p->flags & EVENT_INPUT) FD_SET(p->fd, &in); if (p->flags & EVENT_OUTPUT) FD_SET(p->fd, &out); if (p->flags & EVENT_EXCEPT) FD_SET(p->fd, &except); if (p->fd > max) max = p->fd; } yaz_log(man->log_level, "max=%d sel_fd=%d", max, man->sel_fd); if (man->sel_fd != -1) { if (man->sel_fd > max) max = man->sel_fd; FD_SET(man->sel_fd, &in); } yaz_log(man->log_level, "select begin nofds=%d", max); res = select(max + 1, &in, &out, &except, timeout); yaz_log(man->log_level, "select returned res=%d", res); if (res < 0) { if (errno == EINTR) continue; else { yaz_log(YLOG_ERRNO | YLOG_WARN, "select"); return 0; } } if (man->sel_fd != -1) { if (FD_ISSET(man->sel_fd, &in)) { IOCHAN chan; yaz_log(man->log_level, "eventl: sel input on sel_fd=%d", man->sel_fd); while ((chan = sel_thread_result(man->sel_thread))) { yaz_log(man->log_level, "eventl: got thread result chan=%p name=%s", chan, chan->name ? chan->name : ""); chan->thread_users--; } } } if (man->log_level) { int no = 0; for (p = start; p; p = p->next) { no++; } yaz_log(man->log_level, "%d channels", no); } for (p = start; p; p = p->next) { time_t now = time(0); if (p->destroyed) { yaz_log(man->log_level, "eventl: skip destroyed chan=%p name=%s", p, p->name ? p->name : ""); continue; } if (p->thread_users > 0) { yaz_log(man->log_level, "eventl: skip chan=%p name=%s users=%d", p, p->name ? p->name : "", p->thread_users); continue; } p->this_event = 0; if (p->max_idle && now - p->last_event > p->max_idle) { p->last_event = now; p->this_event |= EVENT_TIMEOUT; } if (p->fd >= 0) { if (FD_ISSET(p->fd, &in)) { p->last_event = now; p->this_event |= EVENT_INPUT; } if (FD_ISSET(p->fd, &out)) { p->last_event = now; p->this_event |= EVENT_OUTPUT; } if (FD_ISSET(p->fd, &except)) { p->last_event = now; p->this_event |= EVENT_EXCEPT; } } run_fun(man, p); } assert(inv_start == start); yaz_mutex_enter(man->iochan_mutex); for (nextp = iochans; *nextp;) { IOCHAN p = *nextp; if (p->destroyed && p->thread_users == 0) { *nextp = iochan_destroy_real(p); } else nextp = &p->next; } yaz_mutex_leave(man->iochan_mutex); } while (*iochans); return 0; }