libevent(二)event_assign
程序员文章站
2022-06-01 09:20:42
...
信号或套接字都可以作为一个event的监听对象,并且一个信号或套接字可同时加入到多个event。
结构体struct event_base
结构体struct event:
struct event {
struct event_callback ev_evcallback;
/* for managing timeouts */
union {
TAILQ_ENTRY(event) ev_next_with_common_timeout;
size_t min_heap_idx;
} ev_timeout_pos;//管理定时器事件
evutil_socket_t ev_fd;//监听对象套接字或信号
struct event_base *ev_base;//所属event_base
union {13
/* used for io events */
struct {
LIST_ENTRY (event) ev_io_next;
struct timeval ev_timeout;
} ev_io;//套接字对象
/* used by signal events */
struct {
LIST_ENTRY (event) ev_signal_next;
short ev_ncalls;
/* Allows deletes in callback */
short *ev_pncalls;
} ev_signal;//信号对象
} ev_;
short ev_events;//监听事件类型EV_READ...
short ev_res; //**事件类型 /* result passed to event callback */
struct timeval ev_timeout;//定时器超时值
};
struct event_callback {
TAILQ_ENTRY(event_callback) evcb_active_next;//**队列
short evcb_flags;
ev_uint8_t evcb_pri;//event的优先级 /* smaller numbers are higher priority */
ev_uint8_t evcb_closure;
/* allows us to adopt for different types of events */
union {
void (*evcb_callback)(evutil_socket_t, short, void *);
void (*evcb_selfcb)(struct event_callback *, void *);
void (*evcb_evfinalize)(struct event *, void *);
void (*evcb_cbfinalize)(struct event_callback *, void *);
} evcb_cb_union;//回调函数
void *evcb_arg;//回调函数参数
};
创建event
struct event *
event_new(struct event_base *base, evutil_socket_t fd, short events, void (*
cb)(evutil_socket_t, short, void *), void *arg)
{
struct event *ev;
ev = mm_malloc(sizeof(struct event));
if (ev == NULL)
return (NULL);
if (event_assign(ev, base, fd, events, cb, arg) < 0) {
mm_free(ev);
return (NULL);
}
return (ev);
}
int
event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short
events, void (*callback)(evutil_socket_t, short, void *), void *arg)
{
if (!base)
base = current_base;//current_base为全局指针,被初始化为NULL
if (arg == &event_self_cbarg_ptr_)//event_self_cbarg_ptr_为全局指针,初始化为NULL
arg = ev;
if (!(events & EV_SIGNAL))
event_debug_assert_socket_nonblocking_(fd);//如果event不是信号,判断套接字是否为非阻塞
event_debug_assert_not_added_(ev);//判断此event是否是没有被"add"
ev->ev_base = base;
ev->ev_callback = callback;
ev->ev_arg = arg;
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
ev->ev_ncalls = 0;
ev->ev_pncalls = NULL;
if (events & EV_SIGNAL) {
if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) {
event_warnx("%s: EV_SIGNAL is not compatible with "
"EV_READ, EV_WRITE or EV_CLOSED", __func__);
return -1;
}
ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL;//如果event标志是信号,则判断是否还有EV_READ等标志,有就会出错,最后初始化ev_closure。
} else {
if (events & EV_PERSIST) {
evutil_timerclear(&ev->ev_io_timeout);
ev->ev_closure = EV_CLOSURE_EVENT_PERSIST;
} else {
ev->ev_closure = EV_CLOSURE_EVENT;
}
}//如果event为套接字(文件描述符)标志,则判断event是否设置EV_PERSIST标志,并设置ev_closure为对应宏
min_heap_elem_init_(ev);
if (base != NULL) {
/* by default, we put new events into the middle priority */
ev->ev_pri = base->nactivequeues / 2;//初始优先级
}
event_debug_note_setup_(ev);//加入event到全局队列global_debug_map
return 0;
}
event_assign初始化中,会将ev_flag初始化为EVLIST_INIT。
event2/event_struct.h
#define EVLIST_TIMEOUT 0x01//event从属于定时器队列或者时间堆
#define EVLIST_INSERTED 0x02//event从属于注册队列
#define EVLIST_SIGNAL 0x04//没有使用
#define EVLIST_ACTIVE 0x08//event从属于活动队列
#define EVLIST_INTERNAL 0x10//该event是内部使用的。信号处理时有用到
#define EVLIST_ACTIVE_LATER 0x20
#define EVLIST_FINALIZING 0x40
#define EVLIST_INIT 0x80//event已经被初始化了
#define EVLIST_ALL 0xff//所有标志。这个不能取