Chromium on the implementation of Chromium main message loop on android:android system

Source: Internet
Author: User

Absrtact: When I first approached chromium on Android, it was curious how chromium's main message loop was integrated into Android apps. For Android programs, once started, the main thread will have a Java layer of message loop processing user input events and other system events, and for chromium, it has its own another set of message loop implementation, which features, and how seamlessly integrated into Android The Java layer's message loop is the topic that this article is going to discuss.

Original article series, reproduced please indicate the original source for http://blog.csdn.net/hongbomin/article/details/41258469.

message loops and main message loops

A message loop, or event loop, is an important concept in the asynchronous programming model that handles asynchronous events that occur in a single thread, including user input events, system events, timer and asynchronous tasks distributed between threads.

The Chromium system abstracts the message loop into the Messageloop class, which specifies that each thread can run at most one Messageloop instance at a time, and Messageloop provides a Posttask series method that allows new asynchronous tasks to be added to the task queue. When Messageloop discovers that a new task arrives, it from Samsara queries its own task queue and executes the task from "FIFO" until the Messageloop::quit message is received and the message loop exits.

Chromium divides messageloop into several different types according to the asynchronous events that are required to be handled:

    • type_default: The default message loop, can only handle timer timer and asynchronous task;
    • type_ui: Not only can handle timer timer and asynchronous task, also can handle the system UI event, the main thread uses this type of messageloop, that is, the main message loop;
    • Type_io: Supports asynchronous IO events, chromium all IO threads that process IPC messages are created with messageloop of that type;
    • Type_java: The message loop type designed for the Android platform, the backend implementation is the JAVA layer's message processor, used to perform tasks added to the Messageloop, with the same behavior as the TYPE_UI type. However, the Messagepump factory method on the main thread cannot be used when creating. Note: This type of messageloop is not related to the message loop discussed in this article.

Messageloop specific implementation of the platform-related, even on the same platforms, due to the use of different event processing libraries, the implementation of the way may be different. Chromium encapsulates platform-related implementations in Messagepump abstract classes, and the relationship between classes Messageloop and Messagepump is as follows:


Messagepump's implementation provides platform-related asynchronous event handling, while Messageloop provides the basic framework for polling and dispatching asynchronous tasks, both by Messagepump::D elegate abstract interfaces.

The basic code skeleton for Messagepump::run is as follows:

for (;;) {  bool did_work =dointernalwork ();  if (should_quit_) break    ;   Did_work |= delegate_->dowork ();  if (should_quit_) break    ;   Timeticks Next_time;  Did_work |=delegate_->dodelayedwork (&next_time);  if (should_quit_) break    ;   if (did_work)    continue;   Did_work =delegate_->doidlework ();  if (should_quit_) break    ;   if (did_work)    continue;   Waitforwork ();}
In the code snippet above, there are three points that need special instructions:

    • Messagepump is responsible for responding to asynchronous events in the system and for giving enough time fragments to dispatch delegate to perform asynchronous tasks, so messagepump calls Dointernalwork,dowork in a mixed interleaved manner. Dodelayedwork and doidlework to ensure that any type of mission does not suffer from "starvation" in the event of non-implementation;
    • Both Dointernalwork and Waitforwork are private methods that messagepump specifically implement. Dointernalwork is responsible for distributing the next UI event or notifying the next IO completion event, while Waitforwork blocks the Messagepump::run method until the current task needs to be executed;
    • Each messagepump has a set should_quit_ tag bit, once the messagepump::quit is called, Should_quit_ will be true, each time messagepump to complete a class of tasks to check Should_ Quit_ flag to determine whether to continue processing subsequent tasks, and when Should_quit_ is found to be true, jump out of the for loop body directly.

nested message loops (Nested messageloop)

If the message loop is likened to a dream that needs to do a lot of things, then the nested message loop is "Inception", moving from one dream to another.

Simply put, a nested message loop is one in which the current message loop enters another message loop because it executes a task, and the current message loop is forced to wait for the nested message loop to exit before continuing with the subsequent task, for example, when the MessageBox dialog box pops up, it means entering a new message loop. This message loop will not exit until the MessageBox's OK or Cancel button is pressed.

Runloop is a class introduced by chromium in the later code refactoring, mainly for developers to use nested message loops more conveniently, each runloop has a run_depth value that represents the number of nested layers, only if run_ A depth value greater than 1 o'clock indicates that the runloop is nested. Runloop is a very special object, it is created on the stack, when the Messageloop::run function is completed, Runloop is automatically released:

void Messageloop::run () {  runloop run_loop;  Run_loop. Run ();}

Each messageloop has a pointer to the currently running Runloop instance, messageloop::current () when the Runloop::run method is called. The Runloop pointer in the message loop is also modified to the currently running Runloop, in other words, if messageloop::current ()->posttask is called at this point, the asynchronous task is executed in the nested message loop.

The basic use of nested message loops is shown in the following code:

void Runnestedloop (runloop* run_loop) {   messageloop::scopednestabletaskallower allow (Messageloop::current ());   Run_loop->run ();  }} Create a new Runlooprunloop nested_run_loop on the stack; Asynchronously initiates a nested message loop in the current message loop; Messageloop::current ()->posttask (From_here, Base::bind (&runnestedloop,unretained (&nested_run_loop))); /Once Runnestedloop executes, the Runloop pointer inside Messageloop::current () points to Nested_run_loop, Posttask will perform a quit operation on the nested runloop Messageloop::current ()->posttask (From_here, Nested_run_loop. Quitclosure ());//When Task_callback is executed asynchronously, the nested runloop is now exited, restored to the original message queue execution; Messageloop::current ()->posttask (from_ Here,task_callback);

the message loop mechanism of the Android system

The fundamentals of the message loop mechanism on the Android platform are very similar to the chromium system, but the abstraction of the Android message loop is built on the Java layer.

In the Android system, Android.os.Looper and Android.os.Handler are two very important classes in the message loop mechanism.

Looper similar to Chromium's messageloop (or runloop) concept, each thread in the Android system can be associated with a looper for handling asynchronous messages or Runable objects. Android system threads are not associated with any looper by default, and developers can explicitly call Looper.prepare and Looper.loop to create and run Looper for threads until they exit Looper. The interaction between looper needs to be done through the class handler.

Handler allows a developer to send or process messages and runable objects to a thread's message queue, which has two uses: 1) asynchronously handles Message Queuing in its own thread through the Handlemessage method ; 2) Send messages to other threads ' message queues through the SendMessage or POST method series. When a thread can have multiple handler,looper polling message queues, it is the responsibility to send the message to the target handler, which is handled by the handlemessage of the target handler.

The relationship between Looper and handler is as shown (image from here):


chromium using the Android message loop mechanism

The main discussion here is the message loop for the main thread, the UI thread, because the IO thread is created at the native layer and does not involve interactive events with UI elements, and Android is also a POSIX system, regardless of the integration of the IO thread message loop.

As mentioned above, the Android message loop is built on the Java layer, chromium need to solve the problem, how to integrate the C + + layer management and dispatch of asynchronous task Messageloop on the control path of the Android system on the main thread. The answer, of course, is to use Android.os.Handler.

First look at the Android platform on the Messagepumpforui specific implementation. Unlike other platforms, the Messagepumpforui implementation, which starts the entire message loop processing logic, does nothing, and instead adds a new start method to enable the Android system's message loop in chromium, as shown in the following code:

void Messagepumpforui::run (delegate* Delegate) {  notreached () << "unittests should rely on Messagepumpforuistub in  test_stub_android.h ";} void Messagepumpforui::start (delegate* Delegate) {  run_loop_ = Newrunloop ();  Since the Runloopwas just created above, Beforerun should is guaranteed to  //return True (Itonly returns False if The Runloop has been Quit already).  if (!run_loop_->beforerun ())    notreached ();  jnienv* env =base::android::attachcurrentthread (); System_message_handler_obj_. Reset (     java_systemmessagehandler_create (          env,reinterpret_cast<intptr_t> (delegate)));}

The Start method makes a request to the Java layer via JNI to create a systemmessagehandler that inherits from Android.os.Handler, adding a new handler type to the Looper of the current UI thread, which provides its own Handlemessage method:

Class Systemmessagehandler extends Android.os.Handler {    private staticfinal int scheduled_work = 1;    Private staticfinal int delayed_scheduled_work = 2;    Privatesystemmessagehandler (Long messagepumpdelegatenative) {       mmessagepumpdelegatenative = messagepumpdelegatenative;    }    @Override public    voidhandlemessage (Message msg) {        if (msg.what== delayed_scheduled_work) {           mdelayedscheduledtimeticks = 0;        }       Nativedorunlooponce (mmessagepumpdelegatenative,mdelayedscheduledtimeticks);} ...}

So, how does the chromium system C + + layer take the request that executes the asynchronous task to the handler of the Androidjava layer, and how does handler perform the asynchronous task at the chromiumc++ layer?

The C + + layer sends asynchronous tasks to the Java layer

Each time the C + + layer adds a new asynchronous task to the UI thread's Messageloop by calling Messageloop::current ()->posttask*, Messageloop::schedulework initiates the action of the scheduled task execution , while Messageloop::schedulework is requesting messagepump to complete this action, whose invocation chain is:


So Messagepumpforui's schedulework needs to send a request from the C + + layer to the Java layer's Systemmessagehandler:

void Messagepumpforui::schedulework () {  jnienv* env =base::android::attachcurrentthread ();  Java_systemmessagehandler_schedulework (env,     system_message_handler_obj_.obj ());}

Accordingly, Systemmessagehandler's Schedulework implementation code is as follows:

Class Systemmessagehandler extends Handler {   ...   @CalledByNative    Private Voidschedulework () {       sendemptymessage (scheduled_work);   }   ...}

It is not difficult to see that the only thing systemmessagehandler.schedulework to do is to send a type scheduled_work message to the UI thread's message queue. Now let's look at how the Java layer handles this type of message.

Java Layer handler handles asynchronous tasks from the C + + layer

When the looper of the UI thread receives this scheduled_work asynchronous message, it is correctly distributed to Systemmessagehandler, This message is handled by the Systemmessagehandler.handlemessage overloaded method, as shown in the code above, Handlemessage executes a native method defined in Messagepumpforui dorunlooponce, whose implementation code is Under

static void Dorunlooponce (jnienv* env, Jobject obj, Jlong native_delegate, Jlong delayed_scheduled_time_ticks) {  Base::messagepump::D elegate* Delegate =      reinterpret_cast<base::messagepump::D elegate*> (native_delegate );  BOOL Did_work =delegate->dowork ();  Base::timeticksnext_delayed_work_time;  Did_work |=delegate->dodelayedwork (&next_delayed_work_time);   if (!next_delayed_work_time.is_null ()) {    if (delayed_scheduled_time_ticks = = 0 | |       Next_delayed_work_time < Base::timeticks::frominternalvalue (           delayed_scheduled_time_ticks)) {     Java_ Systemmessagehandler_scheduledelayedwork (env, obj,         next_delayed_work_time. Tointernalvalue (),         (Next_delayed_work_time-          base::timeticks::now ()). Inmillisecondsroundedup ());    }  }  if (did_work)    return;   Delegate->doidlework ();}

The Dorunlooponce method gives the C + + layer Messageloop the opportunity to handle its own asynchronous tasks, including deferred tasks and idle tasks.

At this point, through the implementation of Messagepumpforui and Systemmessagehandler, the chromium system can be seamlessly integrated into the Android message loop on the main thread,

Summary

The handler class provided by the Android SDK provides considerable convenience for the chromium system to seamlessly integrate its own message loops into the Android system, Chromium's Messageloop sends an asynchronous message to the Java layer's handler via JNI, and when Looper dispatches the asynchronous message, The Java layer's message processor is called by the native method through JNI call chromium Messageloop to invoke the execution of the asynchronous task, thus completing the Chromium browser on the main thread with the Android system message loop integration work.

Original article series, reproduced please indicate the original source for http://blog.csdn.net/hongbomin/article/details/41258469.


Chromium on the implementation of Chromium main message loop on android:android system

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.