[Kernel Research] Message Queue _ messagequeue

Source: Internet
Author: User

The message queue processes the message in queue mode. A first-come message is processed first. However, if the message itself specifies the time to be processed, the message must wait until the time. Messages are represented by the message class in messagequeue. messages in the queue are saved in a linked list structure. The message object contains a next variable, which points to the next message object.

The two main functions in messagequeue are "retrieve message" and "add message", which are next () and enquencemessage ().


Next () function

final Message next() {        int pendingIdleHandlerCount = -1; // -1 only during first iteration        int nextPollTimeoutMillis = 0;        for (;;) {            if (nextPollTimeoutMillis != 0) {                Binder.flushPendingCommands();            }            nativePollOnce(mPtr, nextPollTimeoutMillis);            synchronized (this) {                // Try to retrieve the next message.  Return if found.                final long now = SystemClock.uptimeMillis();                final Message msg = mMessages;                if (msg != null) {                    final long when = msg.when;                    if (now >= when) {                        mBlocked = false;                        mMessages = msg.next;                        msg.next = null;                        if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);                        return msg;                    } else {                        nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);                    }                } else {                    nextPollTimeoutMillis = -1;                }                // If first time, then get the number of idlers to run.                if (pendingIdleHandlerCount < 0) {                    pendingIdleHandlerCount = mIdleHandlers.size();                }                if (pendingIdleHandlerCount == 0) {                    // No idle handlers to run.  Loop and wait some more.                    mBlocked = true;                    continue;                }                if (mPendingIdleHandlers == null) {                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];                }                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);            }            // Run the idle handlers.            // We only ever reach this code block during the first iteration.            for (int i = 0; i < pendingIdleHandlerCount; i++) {                final IdleHandler idler = mPendingIdleHandlers[i];                mPendingIdleHandlers[i] = null; // release the reference to the handler                boolean keep = false;                try {                    keep = idler.queueIdle();                } catch (Throwable t) {                    Log.wtf("MessageQueue", "IdleHandler threw exception", t);                }                if (!keep) {                    synchronized (this) {                        mIdleHandlers.remove(idler);                    }                }            }            // Reset the idle handler count to 0 so we do not run them again.            pendingIdleHandlerCount = 0;            // While calling an idle handler, a new message could have been delivered            // so go back and look again for a pending message without waiting.            nextPollTimeoutMillis = 0;        }    }

The internal flow of the function is divided into three steps:

1. Call nativepollonce (mptr, int time ). This is a JNI function used to retrieve a message from the message queue. The messagequeue class does not store the Message Queue itself. The real message queue data is saved in the C code of JNI. In the C environment, a nativemessagequeue data object is created. This is nativepollonce () the meaning of the first parameter. It is an int type variable. In the C environment, the variable is forcibly converted to an nativemessagequeue object. In the C environment, if there is no message in the message queue, the current thread will be suspended (wait). If there is a message in the message queue, the message is assigned to the mmessages variable in the Java environment in the C code.

2. The following code is included in synchronized (this). This is used as a lock for Retrieving messages and writing messages. It only determines whether the execution time specified by the message has arrived. If the message arrives, the message is returned and the mmessages variable is null. If the time is not reached, the next message is read.

3. If mmessages is empty, the message queue in the C environment has no executable messages. Therefore, run the "Idle callback function" in the mpendingidlehanlder list ". You can register some "Idle callback functions" with messagequeue to execute these "Idle code" when no messages in the thread can be processed ".


Enquencemessage () function

final boolean enqueueMessage(Message msg, long when) {        if (msg.when != 0) {            throw new AndroidRuntimeException(msg                    + " This message is already in use.");        }        if (msg.target == null && !mQuitAllowed) {            throw new RuntimeException("Main thread not allowed to quit");        }        final boolean needWake;        synchronized (this) {            if (mQuiting) {                RuntimeException e = new RuntimeException(                    msg.target + " sending message to a Handler on a dead thread");                Log.w("MessageQueue", e.getMessage(), e);                return false;            } else if (msg.target == null) {                mQuiting = true;            }            msg.when = when;            //Log.d("MessageQueue", "Enqueing: " + msg);            Message p = mMessages;            if (p == null || when == 0 || when < p.when) {                msg.next = p;                mMessages = msg;                needWake = mBlocked; // new head, might need to wake up            } else {                Message prev = null;                while (p != null && p.when <= when) {                    prev = p;                    p = p.next;                }                msg.next = prev.next;                prev.next = msg;                needWake = false; // still waiting on head, no need to wake up            }        }        if (needWake) {            nativeWake(mPtr);        }        return true;    }
The function is divided into two steps:

1. Assign the msg parameter to mmessages.

2. Call nativewake (mptr ). This is a JNI function that adds mmessages messages to message queues in the C environment. If the message thread is in the suspended (wait) state, it will wake up.

[Kernel Research] Message Queue _ messagequeue

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.