• libevent源码分析:event_assign、event_new


    在libevent中,获取event类型对象的方法有两种,event_assign、event_new

    1、event_assign()

     1 /**
     2   Prepare a new, already-allocated event structure to be added.
     3 
     4   The function event_assign() prepares the event structure ev to be used
     5   in future calls to event_add() and event_del().  Unlike event_new(), it
     6   doesn't allocate memory itself: it requires that you have already
     7   allocated a struct event, probably on the heap.  Doing this will
     8   typically make your code depend on the size of the event structure, and
     9   thereby create incompatibility with future versions of Libevent.
    10 
    11   The easiest way to avoid this problem is just to use event_new() and
    12   event_free() instead.
    13 
    14   A slightly harder way to future-proof your code is to use
    15   event_get_struct_event_size() to determine the required size of an event
    16   at runtime.
    17 
    18   Note that it is NOT safe to call this function on an event that is
    19   active or pending.  Doing so WILL corrupt internal data structures in
    20   Libevent, and lead to strange, hard-to-diagnose bugs.  You _can_ use
    21   event_assign to change an existing event, but only if it is not active
    22   or pending!
    23 
    24   The arguments for this function, and the behavior of the events that it
    25   makes, are as for event_new().
    26 
    27   @param ev an event struct to be modified
    28   @param base the event base to which ev should be attached.
    29   @param fd the file descriptor to be monitored
    30   @param events desired events to monitor; can be EV_READ and/or EV_WRITE
    31   @param callback callback function to be invoked when the event occurs
    32   @param callback_arg an argument to be passed to the callback function
    33 
    34   @return 0 if success, or -1 on invalid arguments.
    35 
    36   @see event_new(), event_add(), event_del(), event_base_once(),
    37     event_get_struct_event_size()
    38   */
    39 EVENT2_EXPORT_SYMBOL
    40 int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *);

    实现:

    其实event_assign的作用就是把给定的event类型对象的每一个成员赋予一个指定的值。

     1 int
     2 event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
     3 {
     4     if (!base)
     5         base = current_base;
     6     if (arg == &event_self_cbarg_ptr_)
     7         arg = ev;
     8 
     9     event_debug_assert_not_added_(ev);
    10 
    11     ev->ev_base = base;
    12 
    13     ev->ev_callback = callback;
    14     ev->ev_arg = arg;
    15     ev->ev_fd = fd;
    16     ev->ev_events = events;
    17     ev->ev_res = 0;
    18     ev->ev_flags = EVLIST_INIT;
    19     ev->ev_ncalls = 0;
    20     ev->ev_pncalls = NULL;
    21 
    22     if (events & EV_SIGNAL) {
    23         if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) {
    24             event_warnx("%s: EV_SIGNAL is not compatible with "
    25                 "EV_READ, EV_WRITE or EV_CLOSED", __func__);
    26             return -1;
    27         }
    28         ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL;
    29     } else {
    30         if (events & EV_PERSIST) {
    31             evutil_timerclear(&ev->ev_io_timeout);
    32             ev->ev_closure = EV_CLOSURE_EVENT_PERSIST;
    33         } else {
    34             ev->ev_closure = EV_CLOSURE_EVENT;
    35         }
    36     }
    37 
    38     min_heap_elem_init_(ev);
    39 
    40     if (base != NULL) {
    41         /* by default, we put new events into the middle priority */
    42         ev->ev_pri = base->nactivequeues / 2;
    43     }
    44 
    45     event_debug_note_setup_(ev);
    46 
    47     return 0;
    48 }

    2、event_new()

     1 /**
     2   Allocate and asssign a new event structure, ready to be added.
     3 
     4   The function event_new() returns a new event that can be used in
     5   future calls to event_add() and event_del().  The fd and events
     6   arguments determine which conditions will trigger the event; the
     7   callback and callback_arg arguments tell Libevent what to do when the
     8   event becomes active.
     9 
    10   If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then
    11   fd is a file descriptor or socket that should get monitored for
    12   readiness to read, readiness to write, or readiness for either operation
    13   (respectively).  If events contains EV_SIGNAL, then fd is a signal
    14   number to wait for.  If events contains none of those flags, then the
    15   event can be triggered only by a timeout or by manual activation with
    16   event_active(): In this case, fd must be -1.
    17 
    18   The EV_PERSIST flag can also be passed in the events argument: it makes
    19   event_add() persistent until event_del() is called.
    20 
    21   The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported
    22   only by certain backends.  It tells Libevent to use edge-triggered
    23   events.
    24 
    25   The EV_TIMEOUT flag has no effect here.
    26 
    27   It is okay to have multiple events all listening on the same fds; but
    28   they must either all be edge-triggered, or all not be edge triggerd.
    29 
    30   When the event becomes active, the event loop will run the provided
    31   callbuck function, with three arguments.  The first will be the provided
    32   fd value.  The second will be a bitfield of the events that triggered:
    33   EV_READ, EV_WRITE, or EV_SIGNAL.  Here the EV_TIMEOUT flag indicates
    34   that a timeout occurred, and EV_ET indicates that an edge-triggered
    35   event occurred.  The third event will be the callback_arg pointer that
    36   you provide.
    37 
    38   @param base the event base to which the event should be attached.
    39   @param fd the file descriptor or signal to be monitored, or -1.
    40   @param events desired events to monitor: bitfield of EV_READ, EV_WRITE,
    41       EV_SIGNAL, EV_PERSIST, EV_ET.
    42   @param callback callback function to be invoked when the event occurs
    43   @param callback_arg an argument to be passed to the callback function
    44 
    45   @return a newly allocated struct event that must later be freed with
    46     event_free().
    47   @see event_free(), event_add(), event_del(), event_assign()
    48  */
    49 EVENT2_EXPORT_SYMBOL
    50 struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *);

    实现:

    event_new的实现其实是间接的调用的event_assign,首先调用mm_malloc分配一块内存,然后调用event_assign来给event类型的对象各个成员赋值。

     1 struct event *
     2 event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg)
     3 {
     4     struct event *ev;
     5     ev = mm_malloc(sizeof(struct event));
     6     if (ev == NULL)
     7         return (NULL);
     8     if (event_assign(ev, base, fd, events, cb, arg) < 0) {
     9         mm_free(ev);
    10         return (NULL);
    11     }
    12 
    13     return (ev);
    14 }

    3、区别

    这两种方式的区别就是,event_assign是在栈上分配一个对象,然后给成员赋值;而event_new是在堆上分配一个对象,然后给成员赋值。

  • 相关阅读:
    Windows 创建 Redis 和 zookeeper 系统服务
    mysql 5.7 非正常安装,无法启动 服务没有报告任何错误
    将整个 project 资源打包
    使用Nexus3搭建Maven私服+上传第三方jar包到本地maven仓库
    所有子模块都要执行的checkstyle检查
    把项目通过maven生产源码包和文档包并发布到自己的私服上
    C#.NET常见问题(FAQ)-在VS程序如何取消.vshost的进程
    C#.NET常见问题(FAQ)-无法直接启动带有类库输出类型的项目怎么办
    C#.NET常见问题(FAQ)-VS如何整个项目中查找字符串
    C#.NET常见问题(FAQ)-如何在系统变量中加入新的环境变量
  • 原文地址:https://www.cnblogs.com/lit10050528/p/5867888.html
Copyright © 2020-2023  润新知