2

我正在学习如何使用 Libevent。虽然我无法理解挂起和活动之间的区别。在我看来,当一个事件被添加到 event_base 并且该事件还没有发生时,它处于挂起状态,而调用者等待的事件发生了,然后处于活动状态,对吗?但是,当我阅读描述时event_pending,看到代码爆炸,它说当事件挂起时,改变内部状态是不好的它,我认为这里的“待定”一词是误解,它应该是“event_active”....我错了吗?

#include <event2/event.h>
#include <stdio.h>

/* Change the callback and callback_arg of 'ev', which must not be
 * pending. */
int replace_callback(struct event *ev, event_callback_fn new_callback,
    void *new_callback_arg)
{
    struct event_base *base;
    evutil_socket_t fd;
    short events;

    int pending;

    pending = event_pending(ev, EV_READ|EV_WRITE|EV_SIGNAL|EV_TIMEOUT,
                        NULL);
    if (pending) {
        /* We want to catch this here so that we do not re-assign a
         * pending event.  That would be very very bad. */
        fprintf(stderr,
            "Error! replace_callback called on a pending event!\n");
        return -1;
    }

    event_get_assignment(ev, &base, &fd, &events,
                     NULL /* ignore old callback */ ,
                     NULL /* ignore old callback argument */);

    event_assign(ev, base, fd, events, new_callback, new_callback_arg);
    return 0;
 }
4

2 回答 2

3

未决事件意味着触发了某些操作并且事件回调的执行在 event_base 中排队。

活动事件意味着事件回调当前正在执行当前线程或其他一些(不要忘记您可以操作来自其他线程的事件,即不运行事件循环)

重新分配一个挂起的事件不是线程安全的操作,你可以在 event.c 中看到它。

我认为,如果您编写单线程应用程序,随时重新分配事件是安全的。

于 2012-09-12T18:51:40.237 回答
2

libevent 书籍报价(http://www.wangafu.net/~nickm/libevent-book/Ref4_event.html):

一旦调用 Libevent 函数来设置事件并将其与事件库相关联,它就会被初始化。此时,您可以添加,这使其在基础中挂起。当事件未决时,如果触发事件的条件发生(例如,其文件描述符更改状态或超时到期),则事件变为活动状态,并运行其(用户提供的)回调函数。

所以 libevent 术语中的“待处理”意味着“刚刚添加到反应器中”。没有动作触发需要获取挂起的事件。我用简单的程序检查了这种行为:

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <event.h>

void read_cb( int sock, short which, void *arg )
{
    printf( "read_cb() called\n" );
    fflush( stdout );
    // while our callback is running event is active
}

int main()
{
    struct event_base *base = event_base_new();

    int fd[ 2 ];
    assert( pipe( fd ) == 0 );

    struct event ev;
    event_set( & ev, fd[ 0 ], EV_READ | EV_PERSIST, read_cb, NULL );
    event_base_set( base, & ev );

    assert( event_add( & ev, NULL ) != -1 );
    // it's pending now, just after adding

    printf( "event_pending( ... ) == %d\n", event_pending( & ev, EV_READ, NULL ) );
    fflush( stdout );

    event_base_loop( base, EVLOOP_ONCE );

    return 0;
}

输出:

event_pending( ... ) == 2

于 2014-11-27T16:45:28.180 回答