в чем разница между ожидающим и активным событием в Libevent?

Я учусь использовать Libevent. Пока я не могу понять разницу между ожидающим и активным. На мой взгляд, когда событие добавляется в базу событий, а событие не произошло, оно находится в состоянии ожидания, в то время как событие, которое ожидает вызывающая сторона, произошло, затем в активном состоянии, это правильно? Однако, когда я читаю описание 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;
 }

person rpbear    schedule 12.09.2012    source источник


Ответы (2)


ожидающее событие означает, что какое-то действие запущено, и выполнение обратного вызова события поставлено в очередь в event_base.

активное событие означает, что обратный вызов события в настоящее время выполняется текущим потоком или каким-либо другим (не забывайте, что вы можете манипулировать событиями из другого потока, который не выполняет цикл событий)

Переназначение ожидающего события не является потокобезопасной операцией, вы можете увидеть это в event.c.

Я думаю, что если вы пишете однопоточное приложение, безопасно переназначать событие в любое время.

person gureedo    schedule 12.09.2012
comment
Можете ли вы объяснить ответ, данный @Maxim - person abhiarora; 20.05.2017

цитата из книги 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

person Maxim Ky    schedule 27.11.2014