Libevent source code in-depth analysis 2
-- Reactor Mode
Zhang Liang
As mentioned above, the entire libevent itself is a reactor. Therefore, this section describes the reactor mode and lists the mappings between several important components in libevnet and reactor, the basic concepts described in this section may be mentioned in later sections.
1. Reactor event handling mechanism
First, let's look back at the mechanism of calling a common function: Does a program call a function? Function execution, program waiting? Does the function return the result and control to the program? The program continues processing.
Reactor interprets "reactors" as an event-driven mechanism. Unlike common function calls, an application does not actively call an API to complete processing. Instead, the reactor reverses the event processing process, the application must provide the corresponding interfaces and register them with the reactor. If the corresponding time occurs, the reactor will actively call the interfaces registered by the application. These interfaces are also called "Callback functions ". When using libevent, you also want the libevent framework to register corresponding events and callback functions, libevent calls these callback functions to process relevant events (I/O read/write, timing, and signals ).
The reactor can be described as a reactor by using the Hollywood principles: Don't call us. We will call you to inform you.
For example, you apply for a XX Company. After the interview.
The company HR of "common function call mechanism" is relatively lazy and does not remember your contact information. What should you do? You can only call the interview and ask the result by yourself; have you been admitted, it is still rejected;
The "Reactor" company HR wrote down your contact information. After the result is displayed, they will take the initiative to call you to inform you of the fact that you have been admitted or received. You do not have to call to ask the result by yourself, in fact, no. You don't have HR contact information.
2 advantages of reactor Mode
The reactor mode is one of the essential technologies for writing high-performance network servers. It has the following advantages:
1) fast response, without blocking a single synchronization time, although the reactor itself is still synchronized;
2) programming is relatively simple, which can avoid complicated multithreading and synchronization issues to the maximum extent, and avoid overhead of switching multi-thread/process;
3) Scalability: CPU resources can be fully utilized by increasing the number of reactor instances;
4) reusability. The reactor framework is independent of the specific event processing logic and highly reusable;
3 reactor mode framework
When using the reactor model, there are several essential components: Event source, reactor framework, multiplexing mechanism, and event processing program. Let's first look at the overall framework of the reactor model, and then explain each component one by one.
1) event Source
Linux is a file descriptor, while Windows is a socket or handle, which is called a "handle set". A program registers events of interest on the specified handle, such as I/O events.
2) event demultiplexer-multi-channel event distribution mechanism
I/O multiplexing mechanisms provided by the operating system, such as select and epoll.
The program first registers the handle (event source) and its event to event demultiplexer;
When an event arrives, event demultiplexer will send a notification "in the registered handle set, one or more handle events are ready ";
After receiving the notification, the program can process the event without blocking.
It still corresponds to libevent, such as select, poll, and epoll. However, libevent uses the structure eventop for encapsulation and uses a unified interface to support these I/O multiplexing mechanisms, to hide the underlying system mechanism.
3) reactor -- Reactor
A reactor is an interface for event management. It uses event demultiplexer to register and deregister events internally, and runs an event loop. When an event enters the "ready" status, call the callback function of the registration event to process the event.
Corresponding to the libevent, which is the event_base struct.
A typical reactor declaration method
Class reactor <br/>{< br/> Public: <br/> int register_handler (event_handler * phandler, int event); <br/> int remove_handler (event_handler * phandler, int event); <br/> void handle_events (timeval * PTV); <br/> //... <br/> };
4) Event Handler -- event handler
The event handler provides a set of interfaces, each of which corresponds to a type of event for the reactor to call when the corresponding event occurs and execute the corresponding event processing. Usually it binds a valid handle.
Corresponds to the libevent, which is the event struct.
The following two typical event handler class declaration methods have advantages and disadvantages for each other.
Class event_handler <br/>{< br/> Public: <br/> virtual void handle_read () = 0; <br/> virtual void handle_write () = 0; <br/> virtual void handle_timeout () = 0; <br/> virtual void handle_close () = 0; <br/> virtual handle get_handle () = 0; <br/> //... <br/>}; <br/> class event_handler <br/>{< br/> Public: <br/> // events maybe read/write/timeout/close. ETC <br/> virtual void handle_events (INT events) = 0; <br/> virtual handle get_handle () = 0; <br/> //... <br/> };
4. Reactor event handling process
As mentioned above, the reactor has "Reversed" the event stream. So what is the event control flow like after the reactor mode is used?
See the following sequence diagram.
5 Summary
The above describes the basic concepts, frameworks, and processing procedures of reactor. After a basic clear understanding of the reactor, it is easier to understand libevent, next, we will officially enter the libevent code world. Come on!
References:
Pattern-oriented software architecture, patterns for concurrent and networked objects, Volume 2