Chrome source code analysis thread model continued (12)

Source: Internet
Author: User

Let's take a look at the differences between the three messagepumpwin sub-classes. First, the initialization process is different.

Messagepumpforui calls registerclassex to register a window class, creates a window through this class, and registers wndprocthunk as the processing function of the window message. This is a typical window thread practice.

Messagepumpforio calls port _. set (createiocompletionport (invalid_handle_value, null, null, 1); creates a complete port object. Since Io threads need to process all I/O requests in a centralized manner, including communication between all network I/O and processes, and local file I/O, especially when accessing some complex pages, this concurrency is still very high in some cases. The high performance and scalable I/O model called by Microsoft is very suitable for use here.

Messagepumpdefault does almost nothing during initialization.

Apart from the initialization process, each thread processes different messages, which is a significant difference.

The message loop of messagepumpforio is as follows:

Void messagepumpforio: dorunloop (){
For (;;){
// If we do any work, we may create more messages etc., and more work may
// Possibly be waiting in another task group. When we (for example)
// Waitforiocompletion (), there is a good chance there are still more
// Messages waiting. On the other hand, when any of these methods return
// Having done no work, then it is pretty unlikely that calling them
// Again quickly will find any work to do. Finally, if they all say they
// Had no work, then it is a good time to consider sleeping (waiting)
// More work.

Bool more_work_is_plausible = State _-> delegate-> dowork ();
If (State _-> should_quit)
Break;
More_work_is_plausible | = waitforiocompletion (0, null );
If (State _-> should_quit)
Break;
More_work_is_plausible | =
State _-> delegate-> dodelayedwork (& delayed_work_time _);
If (State _-> should_quit)
Break;

If (more_work_is_plausible)
Continue;

More_work_is_plausible = State _-> delegate-> doidlework ();
If (State _-> should_quit)
Break;

If (more_work_is_plausible)
Continue;


Waitforwork (); // wait (sleep) until we have work to do again.
}
}


// Nothing happened.
Return false;
}

We can see that the I/O thread first calls dowork () and dowork (). There is a work_queue _ in the I/O thread, which stores pendingtask, the most important member in this struct is a task pointer. The so-called task, which is similar to the literal meaning, represents a task. Its specific content will be analyzed later. Further in-depth analysis will go into the runtask function of messageloop. Here, the task will call its own general method run () to execute the specific task.

To sum up the above analysis, the I/O thread first executes common tasks, then calls waitforiocompletion (), followed by delayed tasks, idle tasks, and finally calls waitforwork (), block the thread in getqueuedcompletionstatus.

What is waitforiocompletion () doing? Waitforiocompletion processes the I/o that occurs when registeriohandler is called to register all the handles on the current completed port. Here, the handle is mainly created using the createfile method. What we know currently is the file handle, name the port handle. Network I/O is not registered to the completion port for execution. Instead, it is registered as a special task: Watch for execution. Watch has analyzed the previous socket Section and will not be described here.

Let's look at the waitforiocompletion code:

Bool messagepumpforio: waitforiocompletion (DWORD timeout, iohandler * filter ){
Ioitem item;
If (completed_io _. Empty () |! Matchcompletedioitem (filter, & item )){
// We have to ask the system for another IO completion.
If (! Getioitem (timeout, & item ))
Return false;

If (processinternalioitem (item ))
Return true;
}

If (item. Context-> handler ){
If (filter & item. Handler! = Filter ){
// Save this item for later
Completed_io _. push_back (item );
} Else {
Dcheck_eq (item. Context-> handler, item. Handler );
Willprocessioevent ();
Item. Handler-> oniocompleted (item. Context, item. bytes_transfered,
Item. Error );
Didprocessioevent ();
}
} Else {
// The handler must be gone by now, just cleanup the mess.
Delete item. context;
}
Return true;
}

Getioitem is used to call getqueuedcompletionstatus to obtain the handle and event context corresponding to a specific I/O. Unlike some previous completed port instances, the handle structure and event context are actually the same, because they are defined in a struct.

Struct iocontext {
Overlapped;
Iohandler * Handler;
};

After a series of judgments, the iohandler's member function oniocompleted will be called to execute the callback task.

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.