Files
libucore/src/iomux_impl.c
T
2013-12-24 06:21:13 +01:00

152 lines
3.5 KiB
C

#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <assert.h>
#include "ucore/clock.h"
#include "iomux_impl.h"
//dispatchers for the IOMux implementations */
struct IOMux *iomux_create(enum IOMUX_TYPE type)
{
return iomux_create_ex(type, &uc_timeofday_clock);
}
struct IOMux *iomux_create_ex(enum IOMUX_TYPE type, struct UCoreClock *uclock)
{
struct IOMux *mux = calloc(1, sizeof *mux);
int rc = -1;
switch (type) {
case IOMUX_TYPE_DEFAULT:
case IOMUX_TYPE_EPOLL:
rc = iomux_epoll_init(mux);
break;
case IOMUX_TYPE_SELECT:
rc = iomux_select_init(mux);
break;
}
if (rc != 0) {
//try fallback to select
rc = iomux_select_init(mux);
}
if (rc == 0) {
mux->uclock = uclock;
uc_timers_init_ex(&mux->timers, mux->uclock);
} else {
free(mux);
mux = NULL;
}
return mux;
}
void iomux_delete(struct IOMux *mux)
{
mux->delete_impl(mux);
memset(mux, 0xfa, sizeof *mux);
free(mux);
}
//convert the difference between future and now
static inline void future_to_interval(const struct timeval *future,
const struct timeval *now,
struct timeval *result)
{
if (timercmp(future, now, >)) {
timersub(future, now, result);
} else {
result->tv_sec = 0;
result->tv_usec = 0;
}
}
int iomux_run(struct IOMux *mux)
{
for (;;) {
int rc;
struct timeval first_timer;
struct timeval timeout;
struct timeval *timeoutp;;
int has_timers = 0;
if (uc_timers_first(&mux->timers, &first_timer) == 0) {
struct timeval now;
mux->uclock->now(mux->uclock, &now);
future_to_interval(&first_timer, &now, &timeout);
timeoutp = &timeout;
/* TRACEF("now %d %d future %d %d interval %d %d\n", mux->now.tv_sec, mux->now.tv_usec,
first_timer.tv_sec, first_timer.tv_usec,
timeout.tv_sec, timeout.tv_usec);
*/
assert(timeout.tv_sec >= 0);
assert(timeout.tv_usec >= 0);
has_timers = 1;
} else {
timeoutp = NULL; //no timeout
}
rc = mux->run_impl(mux, timeoutp);
if (rc < 0)
return rc;
if (rc == 0 && !has_timers) //no more events, ever
return 0;
}
return 0;
}
int iomux_timers_run(struct IOMux *mux)
{
int event_cnt;
event_cnt = uc_timers_run(&mux->timers);
assert(event_cnt >= 0);
return event_cnt;
}
int iomux_register_fd(struct IOMux *mux, struct IOMuxFD *fd)
{
assert(mux != NULL);
assert(fd != NULL);
assert(fd->callback != NULL);
assert(fd->fd >= 0);
return mux->register_fd_impl(mux, fd);
}
int iomux_unregister_fd(struct IOMux *mux, struct IOMuxFD *fd)
{
assert(mux != NULL);
assert(fd != NULL);
assert(fd->fd >= 0);
return mux->unregister_fd_impl(mux, fd);
}
int iomux_update_events(struct IOMux *mux, struct IOMuxFD *fd)
{
assert(mux != NULL);
assert(fd != NULL);
assert(fd->callback != NULL);
assert(fd->fd >= 0);
return mux->update_events_impl(mux, fd);
}
struct UCoreClock *iomux_get_clock(struct IOMux *mux)
{
return mux->uclock;
}
struct UCTimers *iomux_get_timers(struct IOMux *mux)
{
return &mux->timers;
}