(Original) Open the fog to see the moon-analyze the proactor mode in asio (2), asioproactor

Source: Internet
Author: User

(Original) Open the fog to see the moon-analyze the proactor mode in asio (2), asioproactor

In the previous blog, we mentioned that asynchronous requests are forwarded from the upper layer to the win_iocp_socket_service object at the bottom of the service layer, which forwards requests to the Operating System (Calling windows APIs ), how does the operating system return the result to the application after processing the asynchronous request? Here, it is implemented through iocp (completion port. Let's take a brief look at the basic steps of iocp:

Asio actually follows this step. Let's look back at the simple example in the previous section:

asio::io_service io_service; tcp::socket socket(io_service); boost::asio::async_connect(socket, server_address, connect_handler); io_service.run(); 

The io_service object in the first line is the core of asio, which encapsulates iocp. Creating an io_service is actually creating an iocp object win_iocp_io_service, therefore, the io_service must be referenced in the creation of all subsequent io objects to share the iocp object. The second row creates a socket object that references the iocp object created in the first row. The third row actually forwards asynchronous requests to the bottom service layer win_iocp_socket_service object, it is finally handed over to the operating system. It is related to iocp by its name, because before initiating an asynchronous operation, it first needs to bind the io object with the complete port, so that the subsequent completion event will be sent to the specified completion port.

The specific process of binding io object and iocp object is as follows: async_connect first calls the base_socket <tcp> open method at the base_xxx template layer, base_socket <tcp> calls the open method of the service object stream_socket_service <tcp> at the service layer. stream_socket_service <tcp> also calls the open method of the bottom service object win_iocp_socket_service, the win_iocp_socket_service object delegates the io_service object referenced by the io object (actually win_iocp_io_service) to the do_open method. In the do_open method, the register_handler method is called, in this method, CreateIoCompletionPort is called to bind the io object and iocp object.

After I/O object and iocp object are bound, win_iocp_socket_service calls the api of the operating system to initiate asynchronous operations.

Let's look at the fourth line: io_service.run ();

Io_service: run () is implemented by entrusting win_iocp_io_service: run (). Let's take a look at the internal implementation of run:

size_t win_iocp_io_service::run(boost::system::error_code& ec){ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) {   stop();   ec = boost::system::error_code();   return 0; }  win_iocp_thread_info this_thread; thread_call_stack::context ctx(this, this_thread);  size_t n = 0;  while (do_one(true, ec))   if (n != (std::numeric_limits<size_t>::max)())     ++n; return n;}

Run () first checks whether there are any operations to be processed. If not, the function exits. win_iocp_io_service uses outstanding_work _ to record the number of tasks to be processed. If the value is not 0, the do_one function is commissioned to continue processing. Do_one () calls the GetQueuedCompletionStatus () function internally. This function blocks and waits for the completion of asynchronous events. When an asynchronous event is completed, it calls back the completion event processing function at the application layer, because I/O object and the completion port have been bound when an asynchronous operation is initiated, iocp can call back the asynchronous completion event to the corresponding completion processing function at the application layer.

So far, the asio asynchronous operation process has been completed. After learning about these internal implementation details, let's take a look at a diagram of the proactor mode in asio on the boost official website.

This figure is almost the same as the Proactor pattern in the previous blog. Based on this figure, we can combine the previous analysis to restore the Proactor pattern in asio from the details. Next, let's take a look at the objects in asio respectively:

  • Initiator: the code that the user calls asio;
  • Asynchronous Operation Processor: An Asynchronous Operation Processor that performs Asynchronous operations. After the operations are completed, the completed events are delivered to the completed event queue. The stream_socket_service class is such a processor, because asynchronous operations sent from tcp: socket are processed by it, and it is finally completed by the underlying service object win_iocp_socket_service, win_iocp_socket_service is responsible for binding io objects and io_service objects and calling the operating system api to initiate asynchronous operations. From a high-level perspective, asio's stream_socket_service becomes the Asynchronous Operation processor in Proactor.
  • Asynchronous Operation: defines a series of Asynchronous operations, corresponding to Windows platform, such as AcceptEx, WSASend, WSARecv and other functions. In asio, these functions are encapsulated in the win_iocp_socket_service and resolver_service classes. [1]
  • Completion Handler: the user layer completes the event processor, which is created by the user. It is generally defined through bind or lambda expressions.
  • Completion Event Queue: completes the Event Queue, stores the Completion events sent by the Asynchronous Operation processor. When an asynchronous Event multi-channel splitter removes one of the events, this Event is deleted from the Queue; on Windows, the operating system is responsible for managing the asio completion event queue;
  • Asynchronous Event Demultiplexer: Asynchronous Event multi-channel splitter. Its function is to wait in the Event queue. Once an Event arrives, it is returned to the caller. In Windows, this function is also completed by the operating system. Specifically, it is completed by GetQueuedCompletionStatus, and this function is called by do_one (). Therefore, from the perspective of the senior management, this separator is also the responsibility of io_service. [2]
  • Proactor, the front camera, is responsible for scheduling asynchronous event multi-channel separators to work, and when asynchronous operations are completed, the Completion Handler corresponding to the scheduling. In asio, this part is done by io_service. Windows is win_iocp_io_service. [3]

From the above analysis, we can see that the Proactor mode in asoi is clear, and io_service is at the core position in asio, not only corresponds to a complete port object, it also participates in asynchronous event processing in Proactor mode and starts the event loop, and schedules asynchronous event multi-channel splitters to callback asynchronous events to the application layer.

Next, let's make a summary: io object is responsible for initiating asynchronous operations. During the process of initiating asynchronous operations, stream_socket_service will be entrusted to forward asynchronous operations to the following service layer and finally to the operating system. When I/O object is created, io_service must be referenced to bind the port to the end, and an event processing function must be provided to complete events after asynchronous operations. Io_service starts the event loop, waits for the completion of the asynchronous event, and sends the result of the asynchronous operation back to the user-defined completed event processing function.

[1] [2] [3] http://blog.csdn.net/henan_lujun/article/details/8965044

If you think this article is useful to you, click here for recommendations. Thank you.

C ++ 11 boost technology exchange group: 296561497. You are welcome to exchange technologies.


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.