"Android from source" 02MessageQueue Epoll prototype

Source: Internet
Author: User

1 Opening

The last talk about Looper, we have a general looper of the end (months passed ... )

We all know that a handler should have a MessageQueue,

On which thread the new Handler (if you do not specify the Looper object), the Handler corresponds to the prepare on this thread looper

As shown in the Handler.java code, Mlooper is specified by Looper.mylooper (),

Public Handler (Callback Callback, Boolean async) {        if (find_potential_leaks) {            final class<? extends handler& Gt Klass = GetClass ();            if (Klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) &&                    (Klass.getmodifiers () & modifier.static) = = 0) {                log.w (TAG, "the following Handler class should be STATIC or leaks might occur:" +                    Klass.getcanonicalname ());            }        }        Mlooper = Looper.mylooper ();        if (Mlooper = = null) {            throw new RuntimeException (                "Can ' t create handler inside thread that have not called Loope R.prepare () ");        }        Mqueue = Mlooper.mqueue;        Mcallback = callback;        masynchronous = async;    }

and Looper.mylooper () from this line thread saved Looper objects (deposited at Looper.prepare)

public static Looper Mylooper () {        return sthreadlocal.get ();    }

So, a handler, corresponding to a set of MessageQueue, Thread, Looper

These are "from the source to see Android" 01 from Looper talk about things, then some hard goods



21 Problems introduced

Introduced from a problem, if a handler was created on child thread 12,

Now call Handler.sendemptymessage on the main thread,

Handler how to process this msg on the main thread,

And then from child thread 12 Let handler's handlemessage function handle it?


So this time we're going to introduce a cross-threading event model--epoll,

This tells the CPP Epoll model first Clear,

Next talk about how Android uses this model



3 Epoll Model

Epolldemo.cpp

#include <iostream> #include <vector> #include <queue> #include <pthread.h> #include < unistd.h> #include <sys/epoll.h> #include <assert.h> #include <fcntl.h> #define Num_thread 4# Define Num_length 200#define max_events 20#define uses_epoll#ifdef uses_epoll/**** (1). Create a Epoll descriptor, call Epoll_create () To complete, epoll_create () has an integer parameter of size that tells the kernel to create an event list (collection) with a size descriptor int epoll_create (int size) (2). Set the event of interest to the descriptor and add it to the list of events in the kernel, which needs to be called EPOLL_CTL () to complete. int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) There are three OP parameters, each representing three operations: a. Epoll_ctl_add, add the descriptor to the attention and the structure of the event that concerns it to the list of events in the kernel to B. Epoll_ctl_del, removes the previously added descriptor and the structure of the event of interest to it, removing C from the kernel's list of events. Epoll_ctl_mod, modifies the event of interest (3) that was previously added to the descriptor in the kernel's event list. Waits for the kernel notification event to occur, resulting in a structure list of the descriptor for the event that was completed by Epoll_wait (). Once you get the list of events, you are ready to handle the event. int epoll_wait (int epfd, struct epoll_event * events, int maxevents, int timeout) –epollin, read event –epollout, write event –epollpri, out of band According to the exception event set corresponding to the Select –epollrdhup,tcp connection to the end at least write half shutdown –epollerr, Error event –epollet, set event to edge trigger –epolloneshot, trigger only once, event is automatically deleted*/int G_epollfd;int g_wakefds[2]; #endifvoid awake () {ssize_t nwrite;    do {nwrite = write (G_wakefds[1], "W", 1); } while (Nwrite = =-1);}    void Awoken () {char buffer[16];    ssize_t nread;    do {nread = Read (G_wakefds[0], buffer, sizeof (buffer)); } while ((Nread = =-1) | | | nread = sizeof (buffer));    Using namespace std;void* threadread (void* userdata) {queue<int>* q = (queue<int>*) UserData;    struct Epoll_event events[max_events];        while (true) {int FDS = epoll_wait (G_EPOLLFD, events, max_events, 1000);            if (FDS < 0) {printf ("Epoll_wait error, exit\n");        Break                } for (int i = 0; i < FDS; i++) {if (Events[i].events & Epollin)//Read Event {                printf ("%s,%d/%d\n", "Epollin", I,fds);                    while (!q->empty ()) {Q->pop (); printf ("removed!                \ n ");            }}} awoken (); } return UserData;}        void* ThreadRun (void* userdata) {queue<int>* q = (queue<int>*) Userdata;while (true) {#ifdef Uses_epoll        Q->push (1);        printf ("%ld:%s\n", (long) pthread_self (), "added!");    Awake (); #else #endif usleep (1000*500); } printf ("Exit thread:%ld\n", (long) pthread_self ()); return UserData;} int main (int argc, char const *argv[]) {/**pipe (Build pipeline): 1) header file #include <unistd.h>2) define function: int pipe (int filedes[2]); 3) Letter              Number description: Pipe () creates a pipeline and returns the file descriptor as a parameter filedes array. Filedes[0] is the read end of the pipeline filedes[1] is the write end of the pipeline.    */INT result = pipe (G_WAKEFDS);    ASSERT (result!=0);    result = Fcntl (G_wakefds[0], F_SETFL, O_nonblock);    ASSERT (result!=0);    result = Fcntl (g_wakefds[1], F_SETFL, O_nonblock);    ASSERT (result!=0);    G_EPOLLFD = Epoll_create (max_events);    ASSERT (G_epollfd > 0);    struct Epoll_event Epv = {0, {0}};    Epv.data.ptr = UserData;    EPV.DATA.FD = G_wakefds[0]; Epv.events = Epollin; if (Epoll_ctl (G_EPOLLFD, Epoll_ctl_add, G_wakefds[0], &AMP;EPV) < 0) printf ("Event ADD failed[fd=%d], evnets[%d]\    N ", EPV.DATA.FD, epv.events);    else printf ("Event Add ok[fd=%d], op=%d, evnets[%0x]\n", EPV.DATA.FD, Epoll_ctl_add, epv.events);    Queue<int> Q; vector<pthread_t> v;for (int i = 0; i < Num_thread; ++i) {pthread_t tid;pthread_create (&tid,null,threadrun,&    AMP;Q); V.push_back (TID);}    pthread_t Tid;    Pthread_create (&AMP;TID,NULL,THREADREAD,&AMP;Q);      V.push_back (TID); for (Vector<pthread_t>::const_iterator it = V.begin (); it < V.end (); ++it) Pthread_join (*it,null); return 0; }


The general idea is this:

a.127 Line start build pipeline G_wakefds,g_wakefds[0] is read port, G_wakefds[1] is write port

B.136 creates a global G_EPOLLFD, the Epoll file descriptor, with the maximum number of events supported by this file descriptor

c.144 Row Epoll_ctl creates an event association, associates G_EPOLLFD with G_wakefds[0], fires an event if g_wakefds[0] changes, and the Epoll_event instance created by event 139

D.151-156 creates multiple threads as a producer, produces an int into a queue, calls the awake () function, writes a byte to g_wakefds[1], and triggers an event.

F.158-160 create a consumer to consume the production of int

G. Where 76 lines int FDS = epoll_wait (G_EPOLLFD, events, max_events, 1000); To wait for the producer to produce an int, when G_WAKEFDS[1] has data written, G_wakefds[0] It triggers the event that was just registered, gets the event processed after the registered events (consuming int), and then calls awoken () to empty g_wakefds[0] and into the next round epoll_wait


Note: Production enqueue and consumer dequeue are required to synchronize the lock, this process is omitted here, Android in Java for message implementation of the synchronization lock


4 Running Results



5 Source Download

Http://pan.baidu.com/s/1i3BTWpv


6 Summary

When a thread's message queue does not have a message to process, it waits on the read-side file descriptor of the pipe until another thread wakes it up through the write-side file descriptor of the pipeline. This saves the consumption of CPU resources on the thread.


7 Reference

"Android System source Scenario analysis"-Luo Shenyang

Android NDK Source Code

Android SDK Source Code



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.