Libevent R4: Working with events
Overview
원문은 이곳<ref>http://www.wangafu.net/~nickm/libevent-book/Ref4_event.html</ref>에서 확인할 수 있다.
Libevent의 기본 실행 단위는 event(이벤트)이다. 모든 이벤트는 상태를 가지게 되는데 이는 다음과 같다.
- 파일 디스크립터의 read/write 준비 완료
- 파일 디스크립터의 read/write 준비 중(Egde-triggered IO Only)
- timout 만료
- signal 발생
- 사용자-정의 trigger
이벤트들은 비슷한 주기를 가지게 되는데, 한번 이벤트를 생성하게 되면 initialized 상태가 된다. 이후 event_base 에 등록하게 되면 pending 상태가 된다. 이벤트가 pending 상태에서 특정 조건을 만족하여 trigger(readable/writable, timeout expire) 되게 되면, active 상태가 되면서 등록된 callback 함수가 실행된다. 만약 이벤트가 persistent 로 설정되었다면, 다시 pending 상태로 돌아간다. 만약 persistent 가 아니라면, pending으로 돌아가지 않는다. 이벤트 delete 를 함으로써 pending 상태에서 non-pending 상태로 바꿀 수 있으며, add 를 이용해서 non-pending 에서 pending으로 변경할 수도 있다.
Constructing event objects
새로운 이벤트를 생성하기 위해서는 event_new() 인터페이스를 사용하면 된다.
- Interface
<source lang=c>
- define EV_TIMEOUT 0x01
- define EV_READ 0x02
- define EV_WRITE 0x04
- define EV_SIGNAL 0x08
- define EV_PERSIST 0x10
- define EV_ET 0x20
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
struct event *event_new(struct event_base *base,
evutil_socket_t fd, short what, event_callback_fn cb, void *arg);
void event_free(struct event *event); </source>
event_new() 함수는 같이 넘겨지는 인자 *base 에서 동작하는 이벤트를 생성한다. 그리고 what 인자는 flag 셋인데, 사용가능한 flag 가 위쪽에 나와있다. 만약 fd 가 양수 값으로 설정됐다면, read/write 하고자 하는 파일 디스크립터 값으로 간주된다. 이벤트가 active 되면, 이벤트는 여기서 등록된 cb 함수를 다음의 인자 값과 함께 실행시킨다(fd : 파일 디스크립터, arg: 이벤트 생성시 넘겨준 arg 값)
오류 발생시, event_new() 는 NULL 을 리턴한다.
모든 이벤트는 생성 직후 initialized 상태 혹은 non-pending 상태가 된다. pedning 상태로 만들기 위해서는 event_add() 를 호출해야 한다.(아래에서 설명함)
이벤트를 삭제(메모리 해제)하고 한다면 event_free() 를 사용해야 하며, 해당 이벤트가 pending/active 상태 중에서도 사용 가능하다.(해당 이벤트가 non-pending/inactive 상태일 때 삭제된다)
- Example
<source lang=c>
- include <event2/event.h>
void cb_func(evutil_socket_t fd, short what, void *arg) {
const char *data = arg; printf("Got an event on socket %d:%s%s%s%s [%s]", (int) fd, (what & EV_TIMEOUT)? " timeout" : "", (what & EV_READ)? " read" : "", (what & EV_WRITE)? " write" : "", (what & EV_SIGNAL)? " signal" : "", data);
}
void main_loop(evutil_socket_t fd1, evutil_socket_t fd2) {
struct event *ev1, *ev2; struct timeval five_seconds = {5, 0}; struct event_base *base = event_base_new(); /* The caller has already set up fd1, fd2 somehow, and make them * nonblocking. */ ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, cb_func, (char*)"Reading event"); ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, cb_func, (char*)"Writing event"); event_add(ev1, &five_seconds); event_add(ev2, NULL); event_base_dispatch(base);
} </source>
References
<references />