Libevent R4: Working with events

From 탱이의 잡동사니
Revision as of 10:32, 29 January 2015 by Pchero (talk | contribs)
Jump to navigation Jump to search

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>

  1. define EV_TIMEOUT 0x01
  2. define EV_READ 0x02
  3. define EV_WRITE 0x04
  4. define EV_SIGNAL 0x08
  5. define EV_PERSIST 0x10
  6. 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>

  1. 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 />