[Libevent] event, event_base struct description

Source: Internet
Author: User
Tags epoll

[Libevent] event, event_base struct description
Eventlibevent core-event

Libevent is based on event-driven, and can be seen from the nameEventIs the core of the entire database.Event is the event handler component in the Reactor framework. It provides function interfaces for the Reactor to call an event to execute corresponding event processing. Generally, it is bound with a valid handle.

 

// Structure Description of event in event2/event_struct.h struct event {TAILQ_ENTRY (event) ev_next;/* Add the next event */TAILQ_ENTRY (event) ev_active_next; /* Add the next event */TAILQ_ENTRY (event) ev_signal_next;/* Add the next signal * // * ev_next, ev_active_next and ev_signal_next are both two-way linked list node pointers; they are the fields used by libevent to manage different event types and events in different periods. Libevent uses a two-way linked list to store all registered I/O and Signal events. ev_next is the position of the I/O event in the linked list. It is called "registered event linked list "; similarly, ev_signal_next is the position of the signal event in the signal event linked list; ev_active_next: libevent puts all the activation events into the active list of the linked list, and then traverses the active list for scheduling, ev_active_next indicates the location of the event in the active list; */unsigned int min_heap_idx;/* for managing timeouts indicates the index of the event stored in the min_heap array */struct timeval ev_timeout; // used to save the event timeout time/* min_heap_idx and ev_timeout. For a timeout event, they are the index and supervalue of the event in the small root heap, libevent uses a small root heap to manage scheduled events */struct event_base * ev_base;/* the reactor instance to which the event belongs. This is an event_base struct */int ev_fd; /* For I/O events, it is the bound file descriptor; for signal events, it is the bound signal */short ev_events;/* event-followed event type, it can be of the following types: I/O events: EV_WRITE and EV_READ scheduled events: EV_TIMEOUT signal: EV_SIGNAL auxiliary option: EV_PERSIST, indicating that it is a permanent event defined in Libevent: # define EV_TIMEOUT 0x01 # define EV_READ 0x02 # define EV_WRITE 0x04 # define EV_SIGNAL 0x08 # define EV_PERSIST 0x10 indicates the event type. You can use the "|" operator. combination, it must be noted that the signal and I/O events cannot be set at the same time. It can also be seen that libevent uses the event struct to unify the processing of these three events; */void * ev_arg; /* The callback function parameter void * indicates any type of data. Specify */void (* ev_callback) (int fd, short events, void * arg);/* The callback function of the event, called by ev_base to execute the event processing program. This is a function pointer. The fd parameter corresponds to ev_fd; events corresponds to ev_events; arg corresponds to ev_arg */int ev_pri;/* smaller numbers are higher priority */short ev_ncils;/* The number of times ev_callback is called when the event is ready for execution, usually 1 */short * ev_pncils;/* Allows deletes in callback, pointer, usually pointing to ev_ncils or NULL */int ev_res;/* result passed to event callback, the type of the current active event */int ev_flags;/* libevent is used to mark the event information field, indicating its current status. Possible values include: # define EVLIST_TIMEOUT 0x01 // event in the time heap # define EVLIST_INSERTED 0x02 // event is in the registered event chain table # define EVLIST_SIGNAL 0x04 // not used # define EVLIST_ACTIVE 0x08 // event in the active linked list # define EVLIST_INTERNAL 0x10 // internal use mark # define EVLIST_INIT 0x80 // event has been initialized # define EVLIST_TIMEOUT 0x01/ /event in the time heap # define EVLIST_INSERTED 0x02 // event is in the registered event chain table # define EVLIST_SIGNAL 0x04 // not used # define EVLIST_ACTIVE 0x08 // event in activate # define EVLIST_INTERNAL 0x10 in the linked list // use the internal flag # define EVLIST_INIT 0x80 // the event has been initialized */};

 

Libevent event Management

Starting from the three linked list node pointers and a heap index in the event struct, libevent's event management method can also be seen in the following:

Every time an event changes to the ready state, the libevent moves it to the active event list [priority ].Priority indicates the priority of the event. Then, libevent selects the ready event based on its scheduling policy and calls its cb_callback () function to execute event processing; fill in the parameters of the cb_callback function according to the ready handle and event type.

Interface functions set for event Events

To add an event to libevent, you must first set the event object. The functions provided by calling libevent include:Event_set (), event_base_set (), event_priority_set ()To complete;

Void event_set (struct event * ev, int fd, short events, void (* callback) (int, short, void *), void * arg)

1. set the file descriptor or signal bound to the event ev. For scheduled events, set it to-1. 2. set the event type, such as EV_READ | EV_PERSIST, EV_WRITE, and EV_SIGNAL. 3. set the Event Callback Function and parameter arg; 4. initialize other fields, such as the default event_base and priority;

Int event_base_set (struct event_base * base, struct event * ev)

Set event_base to be registered for event ev; libevent has a global event_base pointer current_base. By default, event ev will be registered on current_base. You can use this function to specify different event_base; if a process contains multiple libevent instances, you must call this function to set different event_base for the event;

Int event_priority_set (struct event * ev, int pri)

There is nothing to say about setting the priority of event ev. Note that when ev is in the ready state and cannot be set,-1 is returned. Event_base event processing framework-event_base
// Event_base is defined in the event-internal.h file struct event_base {const struct eventop * evsel; // represents the selected event engine, which may be: epoll, poll, selectvoid * evbase; // The settings of the Global Object/* evsel and evbase fields may be confusing. Here you can regard evsel and evbase as the relationship between classes and static functions, for example, the call behavior when an event is added: evsel-> add (evbase, ev). The actual operation is evbase. This is equivalent to class: add (instance, ev ), an instance is an object instance of the class. Evsel points to one of the global variables static const struct eventop * eventops []. As mentioned earlier, libevent encapsulates the I/O demultiplex mechanism provided by the system into an eventop structure; therefore, eventops [] contains several global instance objects, such as select, poll, kequeue, and epoll. Evbase is actually an eventop instance object; let's take a look at the eventop struct, whose members are a series of function pointers in the event-internal.h file: struct eventop {const char * name; void * (* init) (struct event_base *); // initialize int (* add) (void *, struct event *); // register the event int (* del) (void *, struct event *); // Delete event int (* dispatch) (struct event_base *, void *, struct timeval *); // event distribution void (* dealloc) (struct event_base *, void *); // deregister and release the resource int need_reinit; // set if we need Reinitialize the event base}; that is to say, in libevent, the implementation of each I/O demultiplex mechanism must provide these five function interfaces to complete its own initialization, destruction, and release; registration, cancellation, and distribution of events. For example, for epoll, libevent Implements Five corresponding interface functions, and points the five function pointers of eventop to these five functions during initialization, then the program can use epoll as the I/O demultiplex Mechanism */int event_count;/* counts number of total events */int event_count_active; /* counts number of active events */int event_gotterm;/* Set to terminate loop */int event_break; /* Set to terminate loop immediately * // * active event management */struct event_list ** activequeues; int nactivequeues;/* is a second-level pointer Libevent supports event priority. Therefore, you can regard it as an array. The element activequeues [priority] is a linked list, each node in the linked list points to a ready event with a priority of priority. */Struct evsignal_info sig;/* signal handling info, is the structure used to manage signals */struct event_list eventqueue; // linked list, saving all the pointers for event registration. Struct min_heap timeheap; // The stack used to detect whether an event times out. It is a small root heap for managing scheduled events. struct timeval event_ TV; // the current time of the system, struct timeval TV _cache; // with event:: ev_timeout is compared to determine whether the event times out. // event_ TV and TV _cache are libevent variables used for time management };
Create and initialize event_base

Creating an event_base object is not only creating a new libevent instance, but also calling event_init ()(The event_base_new () function is called internally to execute a specific operation) to create a function. The function also initializes the newly generated libevent instance.

This function applies for a space for the event_base instance, initializes the timer mini-heap, selects and initializes the demultiplexer mechanism of the appropriate system I/O, and initializes the linked list of events; the function also detects system time settings, laying the foundation for later time management.

Interface functions

The role of the Reactor framework mentioned above isProvides interfaces for event registration and cancellationBased on the multi-channel event distribution mechanism provided by the systemExecute event Loop,When an event enters the "ready" status,Call the callback function of the registration event to process the event.. The main interface functions in Libevent are:

Int event_add (struct event * ev, const struct timeval * timeout ); Int event_del (struct event * ev ); Int event_base_loop (struct event_base * base, int loops ); Void event_active (struct event * event, int res, short events ); Void event_process_active (struct event_base * base );

The following describes the code process for event registration and deletion. The libevent event loop framework will be described in the next article.

For scheduled events, these functions call the timer heap management interface to perform the insert and delete operations; for I/O and Signal events, the add and delete interfaces of eventop are called to perform the insert and delete operations (eventop calls the Signal processing interface to perform operations on Signal events );

 

Register an event

 

Function prototype: int event_add (struct event * ev, const struct timeval * TV) parameter: ev: indicates the event to be registered; TV: timeout time;

The function registers ev to ev-> ev_base. The event type is specified by ev-> ev_events. If the registration is successful, ev is inserted into the registered linked list.If TV is not NULL, the scheduled event will be registered at the same time and ev will be added to the timer stack;

If one operation fails, the function ensures that no event is registered. This is equivalent to an atomic operation.This function also reflects the clever design of libevent details, and carefully looks at the program code. Some of them are omitted, and comments are directly attached to the code.

 

Int event_add (struct event * ev, const struct timeval * TV) {struct event_base * base = ev-> ev_base; // event_baseconst struct eventop * evsel = base-> evsel; void * evbase = base-> evbase; // system I/O policy used by the base // new timer event, call the timer heap interface to reserve a location on the stack // Note: This ensures the atomicity of the operation: // registration with the system I/O mechanism may fail, but after the reservation is successful on the stack, the addition of the // scheduled event will certainly not fail; // The reserved location may result in heap expansion, but the internal element does not change if (TV! = NULL &&! (Ev-> ev_flags & EVLIST_TIMEOUT) {if (min_heap_reserve (& base-> timeheap, 1 + min_heap_size (& base-> timeheap) =-1) return (-1);/* ENOMEM = errno */} // if the event ev is not registered or activated in the linked list, call evbase to register the event if (ev-> ev_events & (EV_READ | EV_WRITE | EV_SIGNAL ))&&! (Ev-> ev_flags & (EVLIST_INSERTED | EVLIST_ACTIVE) {res = evsel-> add (evbase, ev); if (res! =-1) // register successfully. Insert the event to the registered linked list event_queue_insert (base, ev, EVLIST_INSERTED);} // prepare to add the scheduled event if (res! =-1 & TV! = NULL) {struct timeval now; // EVLIST_TIMEOUT indicates that the event is already in the timer heap. Delete the old if (ev-> ev_flags & EVLIST_TIMEOUT) event_queue_remove (base, ev, EVLIST_TIMEOUT); // if the event is ready, delete if (ev-> ev_flags & EVLIST_ACTIVE) & (ev-> ev_res & EV_TIMEOUT) from the active linked list )) {// set the ev_callback call count to 0if (ev-> ev_ncils & ev-> ev_pncils) {* ev-> ev_pncils = 0;} event_queue_remove (base, ev, EVLIST_ACTIVE);} // calculate the time and insert it to the timer small root heap gettime (base, & now); evutil_timeradd (& now, TV, & ev-> ev_timeout ); event_queue_insert (base, ev, EVLIST_TIMEOUT);} return (res );}

Void event_queue_insert (struct event_base * base, struct event * ev, int queue) {// ev may already be in the activation list to avoid repeated insertion of if (ev-> ev_flags & queue) {if (queue & EVLIST_ACTIVE) return ;}//... ev-> ev_flags | = queue; // record the queue tag switch (queue) {case EVLIST_INSERTED: // I/O or Signal event, add the registered event linked list TAILQ_INSERT_TAIL (& base-> eventqueue, ev, ev_next); break; case EVLIST_ACTIVE: // readiness event to the base-> event_count_active ++; TAILQ_INSERT_TAIL (base-> activequeues [ev-> ev_pri], ev, ev_active_next); break; case EVLIST_TIMEOUT: // scheduled event, add min_heap_push (& base-> timeheap, ev); break ;}}

 

Delete event

Function prototype: int event_del (struct event * ev );

This function will delete the event ev. For I/O events, the event is logged out from the demultiplexer of I/O. For Signal eventsDelete the event chain table. For scheduled events, they are deleted from the stack;

Similarly, operations to delete events are not necessarily atomic.For example, after a time event is deleted, cancellation may fail from the system I/O mechanism.

 

Int event_del (struct event * ev) {struct event_base * base; const struct eventop * evsel; void * evbase; // ev_base is NULL, it indicates that ev is not registered if (ev-> ev_base = NULL) return (-1); // get event_base and eventop pointer base = ev-> ev_base for ev registration; evsel = base-> evsel; evbase = base-> evbase; // set the number of ev_callback calls to if (ev-> ev_ncils & ev-> ev_pncils) {* ev-> ev_pncils = 0;} // Delete if (ev-> ev_flags & EVLIST_TIMEOUT) event_queue_remove (base, ev, EVLIST_TIMEOUT) from the corresponding linked list ); if (ev-> ev_flags & EVLIST_ACTIVE) event_queue_remove (base, ev, EVLIST_ACTIVE); if (ev-> ev_flags & EVLIST_INSERTED) {event_queue_remove (base, ev, EVLIST_INSERTED ); // EVLIST_INSERTED indicates that the event is an I/O or Signal event. // you need to call I/O demultiplexer to cancel the event return (evsel-> del (evbase, ev ));} return (0 );}

 

The event_base structure is analyzed,It is preliminarily seen that the libevent encapsulates the event_op structure of the system's I/O demultiplex mechanism.The event registration and deletion processes are analyzed based on the source code. The main event loop section in the event management framework will be analyzed below.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.