事件

#define DEFAULT_EPOLL_TIMEOUT 1000    /* 1 sec  */

static inline uint64_t get_current_msec()
{
    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC, &ts);

    return ts.tv_sec * 1000 + ts.tv_nsec / 1000 / 1000;
}

static inline int64_t run_timers(list_head_t * timer_list)
{
    ev_timer_t *timer;
    int64_t timeout = DEFAULT_EPOLL_TIMEOUT;

    while (!list_empty(timer_list) &&
           (timer = list_first_entry(timer_list, ev_timer_t, list))) {

        timeout = timer->abs_msec - get_current_msec();

        if (timeout <= 0) {    /* expired */
            timer->callback(timer);
            list_del(&timer->list);
            timeout = DEFAULT_EPOLL_TIMEOUT;
        } else {
            break;
        }
    }

    return timeout >
        DEFAULT_EPOLL_TIMEOUT ? DEFAULT_EPOLL_TIMEOUT : timeout;
}

void ev_destory_context(ev_context_t * c)
{
    close(c->efd);
    free(c);
}

ev_context_t *ev_create_context(int max_events)
{
    size_t size;
    ev_context_t *c;

    assert(max_events > 0);

    size = sizeof(ev_context_t) + max_events * sizeof(struct epoll_event);
    c = calloc(size, 1);

    if (!c)
        return NULL;

    c->max_events = max_events;
    c->stopped = 0;
    INIT_LIST_HEAD(&c->timer_list);

    c->efd = epoll_create(max_events);
    if (c->efd == -1) {
        free(c);
        return NULL;
    }
    return c;
}

int ev_run(ev_context_t * c)
{
    int nfds;
    int64_t timeout;
    struct epoll_event *ev;
    ev_event_t *event;
    int n;

    while (!c->stopped) {

        timeout = run_timers(&c->timer_list);

        nfds = epoll_wait(c->efd, c->events, c->max_events, timeout);

        if (nfds == -1) {
            if (errno == EINTR)
                continue;

            return -1;    /* exit, should be never to here */
        }

        for (n = 0; n < nfds; ++n) {
            ev = &c->events[n];
            event = (ev_event_t *) (ev->data.ptr);
            event->callback(event);
        }

    }

    return 0;
}

int ev_register_event(ev_context_t * c, ev_event_t * event)
{
    struct epoll_event ev;

    ev.data.ptr = (void *)event;
    ev.events = event->events;

    return epoll_ctl(c->efd, EPOLL_CTL_ADD, event->fd, &ev);
}

void ev_unregister_event(ev_context_t * c, ev_event_t * event)
{
    epoll_ctl(c->efd, EPOLL_CTL_DEL, event->fd, NULL);
}

void ev_init_timer(ev_timer_t * timer, uint64_t msec,
           ev_timer_callback_t callback)
{
    timer->callback = callback;
    INIT_LIST_NODE(&timer->list);
    timer->msec = msec;
}

void ev_start_timer(ev_context_t * c, ev_timer_t * timer)
{
    ev_timer_t *t;

    timer->abs_msec = get_current_msec() + timer->msec;

    list_for_each_entry(t, &c->timer_list, list) {
        if (t->abs_msec > timer->abs_msec) {
            __list_add(&timer->list, t->list.prev, &t->list);
            run_timers(&c->timer_list);
            return;
        }
    }

    list_add_tail(&timer->list, &c->timer_list);
    run_timers(&c->timer_list);
}

void ev_cancel_timer(ev_context_t * c, ev_timer_t * timer)
{
    UNUSED(c);
    list_del(&timer->list);
}
posted @ 2014-07-17 17:32  holycrap  阅读(198)  评论(0编辑  收藏  举报