Reactors (reactor): Architectural patterns for event multiplexing and dispatch
Typically, there are two ways to work with a file or device that is specified for a file descriptor: blocking and non-blocking. Blocking means that when attempting to read and write to the file descriptor, if there is nothing to read at the time, or is temporarily not writable, the program goes into the waiting state until something is readable or writable. For non-blocking states, if nothing is readable or writable, the read-write function returns immediately without waiting. The example of TCP traffic mentioned in the previous section of
is the blocking way of working: When TCP data is received, if the remote has no data to read, it blocks until it reads the data that is needed. This way of transmission is similar to the traditional passive method invocation, very intuitive, and simple and effective, but there is also a problem of efficiency, if you are developing a thousands of-connected server program, each client in a blocking mode of communication, if there is a very time-consuming reading and writing operations, Other client communications will be unresponsive and inefficient.
A common practice is to create a new thread to communicate with the socket separately (in blocking mode) each time a socket connection is established. This way has a very high response speed, and control is very simple, when the number of fewer connections is very effective, but if each connection to create a thread is undoubtedly a waste of system resources, if the number of connections will be a shortage of resources.
Another more efficient practice is to save a list of socket connections on the server side, and then poll the list, and if you find that there is data readable on a socket port (read-ready), Calls the corresponding read operation of the socket connection, or calls the corresponding write operation of the socket connection if a socket port is found to be writable (write-ready), and the corresponding destructor is called to close the port if a socket connection to the port has been interrupted. This can make full use of server resources, efficiency has been greatly improved.
in socket programming, you can do this by using related APIs such as select. But the direct control of these APIs is cumbersome, and difficult to control and transplant, in the ace can be simplified through the reactor model of the development process.
The reactor essentially provides a more advanced set of programming abstractions, simplifying the design and implementation of event-driven distributed applications. In addition, the reactor integrates multiple separation of several different kinds of events into Easy-to-use APIs. In particular, the reactors deal with timer-based events, signal events, events based on I/O port monitoring, and user-defined notifications uniformly.
The reactors in ACE work in conjunction with several internal and external components. The basic concept is that the reactor framework detects events (by listening on the OS Event multiplexing interface) and emits a "callback" (callback) for the methods in the Pre-registration event handler (event handler) object. This method is implemented by the application developer, which contains the specific code that is used to handle this event.
using Ace's reactors,There are only a few steps:
Create an event handler to handle an event that is of interest to him.
Registered on the reactor, the notice said that he was interested in handling an event while passing the pointer to the reactor of the event handler he wanted to handle the event.
Subsequently the reactor framework will automatically:
Maintain some tables internally, associating different event types with event handler objects.
The reactor issues a callback to the corresponding method in the processor when an event that the user has enlisted occurs.
The reactor mode is implemented as the Ace_reactor class in Ace, which provides the functional interface of the reactor framework.
As mentioned above, the reactor uses the event handler object as a service provider. A related callback method that records specific events for an event handler within the reactor. When these events occur, the reactor creates an association of this event with the corresponding event handler.
Event handlers
Event handlers are objects in the list of objects that need to be changed by polling for events, as in the example above, the connected client, each client can be viewed as an event handler.
Callback Event
Is the event supported by the reactor, such as socket read-ready, write-ready. Take the example above, if a client (event handler) registers a read-ready event in the reactor, the client's data-readable callback function is triggered when the client sends a message to the server.
In the reactor framework, all application-specific event handlers must be derived from the Ace_event_handler abstract interface class. You can implement the associated callback method by overloading the appropriate "Handle_" method.
There are basically three steps to using Ace_reactor:
Create Ace_event_handler subclasses and implement the appropriate "Handle_" method in them to handle the type of event you want this event handler to serve.
Of the reactor object by calling theRegister_handler (), register your event handler with the reactor.
When an event occurs, the reactor automatically recalls the appropriate Handle_ "method for the appropriate event handler object."