libhv icon indicating copy to clipboard operation
libhv copied to clipboard

能否提供一个兼容层,以方便在现有软件中使用libhv替代libevent?

Open he7850 opened this issue 2 years ago • 4 comments

大部分Linux操作系统中,都已经集成了libevent,并且很多关键软件中都大量使用了libevent接口。 如果想要在已有软件中使用libhv替代libevent,必须适配软件中所有使用libevent接口的位置,调整成使用libhv接口,这个修改量是相当大的,非常困难。 但如果libhv能实现libevent库的一些核心接口,那么就可以无需适配下游软件,直接将下游软件使用的头文件换为libhv头文件即可。

想问一下,当前是否有计划在libhv中提供一个兼容层?兼容层实现可以参考libev:http://cvs.schmorp.de/libev/event.c

如果这个兼容层能够实现,像一些国产操作系统社区,比如openEuler,都可以推动将libhv作为核心系统组件集成到系统中,带来更广泛的使用。

he7850 avatar Mar 25 '23 08:03 he7850

兼容层只需实现少量libevent接口。比如说, nfs-utils中使用的:

event_init
event_add
event_del
event_dispatch
event_set
event_initialized

avahi中使用的:

event_new
event_free
event_add
event_del
event_base_free
event_base_new
event_base_dispatch
event_assign
event_base_loopbreak
event_pending
event_get_fd
event_loop

he7850 avatar Mar 27 '23 01:03 he7850

openEuler社区今年在开源之夏有一个项目 ,正好可以用您说的这个思路实现。这个项目目前由我跟进,我会尝试基于libhv实现一个libevent兼容层。

ptbxzrt avatar Jul 13 '23 15:07 ptbxzrt

我写了部分实现,可以参考下:

#ifndef HV_LIBEVENT_COMPAT_H_
#define HV_LIBEVENT_COMPAT_H

#include "hexport.h"
#include "hloop.h"

#define event_base  hloop_s;
#define event       hio_s;

#define EV_READ     HV_READ
#define EV_WRITE    HV_WRITE

typedef int evutil_socket_t;
typedef void (*event_callback_fn)(evutil_socket_t fd, short events, void *callback_arg);

HV_INLINE struct event_base *event_base_new(void) {
    return hloop_new(0);
}

HV_INLINE void event_base_free(struct event_base *eb) {
    hloop_free(&eb);
}

HV_INLINE int event_base_dispatch(struct event_base *eb) {
    return hloop_run(eb);
}

HV_INLINE int event_base_loopbreak(struct event_base *eb) {
    return hloop_stop(eb);
}

HV_INLINE void on_readable(hio_t* io) {
    struct hloop_s *base = hevent_loop(io);
    int fd = hio_fd(io);
    short events = EV_READ;
    event_callback_fn callback = (event_callback_fn)hio_context(io);
    void* callback_arg = (void*)hevent_userdata(io);
    if (callback) {
        callback(base, fd, events, callback_arg);
    }
}

HV_INLINE void on_writable(hio_t* io) {
    struct hloop_s *base = hevent_loop(io);
    int fd = hio_fd(io);
    short events = EV_WRITE;
    event_callback_fn callback = (event_callback_fn)hio_context(io);
    void* callback_arg = (void*)hevent_userdata(io);
    if (callback) {
        callback(base, fd, events, callback_arg);
    }
}

int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, event_callback_fn callback, void *callback_arg) {
    struct hio_s *io = (struct hio_s*)ev;
    // NOTE: use io->context to save callback, event->userdata to save callback_arg
    hio_set_context(io, callback);
    hevent_set_userdata(io, callback_arg);
    if (events & EV_READ) {
        hio_add(io, on_readable, HV_READ);
    }
    if (events & EV_WRITE) {
        hio_add(io, on_writable, HV_WRITE);
    }
    return io;
}

HV_INLINE struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn callback, void *callback_arg) {
    struct hio_s *io = hloop_get(fd);
    event_assign(io, base, fd, events, callback, callback_arg);
    return io;
}

int event_add(struct event *ev, const struct timeval *timeout) {
    void(ev);
    void(timeout);
    return 0;
}

int event_del(struct event *ev) {
    return hio_del(ev);
}

HV_INLINE void event_free(struct event *ev) {
    void(ev);
}

HV_INLINE evutil_socket_t event_get_fd(const struct event *ev) {
    return hio_fd(ev);
}

HV_INLINE int event_pending(const struct event *ev, short events, struct timeval *tv) {
    int added_events = hio_events(ev);
    if (added_events & events) return 1;
    return 0;
}

HV_INLINE int event_initialized(const struct event *ev) {
    void(ev);
    return 1;
}

#endif

ithewei avatar Jul 14 '23 04:07 ithewei

我写了部分实现,可以参考下:

#ifndef HV_LIBEVENT_COMPAT_H_
#define HV_LIBEVENT_COMPAT_H

#include "hexport.h"
#include "hloop.h"

#define event_base  hloop_s;
#define event       hio_s;

#define EV_READ     HV_READ
#define EV_WRITE    HV_WRITE

typedef int evutil_socket_t;
typedef void (*event_callback_fn)(evutil_socket_t fd, short events, void *callback_arg);

HV_INLINE struct event_base *event_base_new(void) {
    return hloop_new(0);
}

HV_INLINE void event_base_free(struct event_base *eb) {
    hloop_free(&eb);
}

HV_INLINE int event_base_dispatch(struct event_base *eb) {
    return hloop_run(eb);
}

HV_INLINE int event_base_loopbreak(struct event_base *eb) {
    return hloop_stop(eb);
}

HV_INLINE void on_readable(hio_t* io) {
    struct hloop_s *base = hevent_loop(io);
    int fd = hio_fd(io);
    short events = EV_READ;
    event_callback_fn callback = (event_callback_fn)hio_context(io);
    void* callback_arg = (void*)hevent_userdata(io);
    if (callback) {
        callback(base, fd, events, callback_arg);
    }
}

HV_INLINE void on_writable(hio_t* io) {
    struct hloop_s *base = hevent_loop(io);
    int fd = hio_fd(io);
    short events = EV_WRITE;
    event_callback_fn callback = (event_callback_fn)hio_context(io);
    void* callback_arg = (void*)hevent_userdata(io);
    if (callback) {
        callback(base, fd, events, callback_arg);
    }
}

int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, event_callback_fn callback, void *callback_arg) {
    struct hio_s *io = (struct hio_s*)ev;
    // NOTE: use io->context to save callback, event->userdata to save callback_arg
    hio_set_context(io, callback);
    hevent_set_userdata(io, callback_arg);
    if (events & EV_READ) {
        hio_add(io, on_readable, HV_READ);
    }
    if (events & EV_WRITE) {
        hio_add(io, on_writable, HV_WRITE);
    }
    return io;
}

HV_INLINE struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn callback, void *callback_arg) {
    struct hio_s *io = hloop_get(fd);
    event_assign(io, base, fd, events, callback, callback_arg);
    return io;
}

int event_add(struct event *ev, const struct timeval *timeout) {
    void(ev);
    void(timeout);
    return 0;
}

int event_del(struct event *ev) {
    return hio_del(ev);
}

HV_INLINE void event_free(struct event *ev) {
    void(ev);
}

HV_INLINE evutil_socket_t event_get_fd(const struct event *ev) {
    return hio_fd(ev);
}

HV_INLINE int event_pending(const struct event *ev, short events, struct timeval *tv) {
    int added_events = hio_events(ev);
    if (added_events & events) return 1;
    return 0;
}

HV_INLINE int event_initialized(const struct event *ev) {
    void(ev);
    return 1;
}

#endif

感谢!

ptbxzrt avatar Jul 14 '23 06:07 ptbxzrt