MessageQueue.cpp revision f1d8e87b09abf963cd5b6a026194c1940fadb7b4
1f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian/*
2f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * Copyright (C) 2009 The Android Open Source Project
3f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian *
4f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
5f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * you may not use this file except in compliance with the License.
6f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * You may obtain a copy of the License at
7f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian *
8f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
9f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian *
10f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * Unless required by applicable law or agreed to in writing, software
11f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
12f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * See the License for the specific language governing permissions and
14f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian * limitations under the License.
15f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian */
16f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
17f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <stdint.h>
18f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <errno.h>
19f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <sys/types.h>
20f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
21f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <utils/threads.h>
22f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <utils/Timers.h>
23f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <utils/Log.h>
24f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include <utils/IPCThreadState.h>
25f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
26f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian#include "MessageQueue.h"
27f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
28f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopiannamespace android {
29f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
30f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian// ---------------------------------------------------------------------------
31f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
32f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias AgopianMessageQueue::MessageQueue()
33f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
34f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    mInvalidateMessage = new MessageBase(INVALIDATE);
35f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
36f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
37f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias AgopianMessageQueue::~MessageQueue()
38f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
39f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
40f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
41f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias AgopianMessageList::NODE_PTR MessageQueue::waitMessage(nsecs_t timeout)
42f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
43f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    MessageList::NODE_PTR result;
44f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    bool again;
45f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    do {
46f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        const nsecs_t timeoutTime = systemTime() + timeout;
47f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        while (true) {
48f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            Mutex::Autolock _l(mLock);
49f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            nsecs_t now = systemTime();
50f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            nsecs_t nextEventTime = -1;
51f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
52f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            // invalidate messages are always handled first
53f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            if (mInvalidate) {
54f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                mInvalidate = false;
55f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                mInvalidateMessage->when = now;
56f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                result = mInvalidateMessage;
57f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                break;
58f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            }
59f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
60f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            result = mMessages.head();
61f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
62f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            if (result != 0) {
63f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                if (result->when <= now) {
64f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    // there is a message to deliver
65f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    mMessages.remove(result);
66f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    result->detach();
67f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    break;
68f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                }
69f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                if (timeout>=0 && timeoutTime < now) {
70f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    // we timed-out, return a NULL message
71f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    result = 0;
72f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    break;
73f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                }
74f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                nextEventTime = result->when;
75f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                result = 0;
76f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            }
77f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
78f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            if (timeout >= 0 && nextEventTime > 0) {
79f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                if (nextEventTime > timeoutTime) {
80f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    nextEventTime = timeoutTime;
81f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                }
82f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            }
83f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
84f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            if (nextEventTime >= 0) {
85f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                //LOGD("nextEventTime = %lld ms", nextEventTime);
86f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                if (nextEventTime > 0) {
87f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    // we're about to wait, flush the binder command buffer
88f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    IPCThreadState::self()->flushCommands();
89f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                    mCondition.wait(mLock, nextEventTime);
90f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                }
91f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            } else {
92f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                //LOGD("going to wait");
93f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                // we're about to wait, flush the binder command buffer
94f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                IPCThreadState::self()->flushCommands();
95f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian                mCondition.wait(mLock);
96f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            }
97f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        }
98f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        // here we're not holding the lock anymore
99f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
100f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        if (result == 0)
101f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            break;
102f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
103f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        again = result->handler();
104f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        if (again) {
105f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            // the message has been processed. release our reference to it
106f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            // without holding the lock.
107f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian            result = 0;
108f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        }
109f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
110f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    } while (again);
111f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    return result;
112f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
113f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
114f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopianstatus_t MessageQueue::postMessage(
115f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags)
116f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
117f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    return queueMessage(message, relTime, flags);
118f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
119f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
120f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopianstatus_t MessageQueue::invalidate() {
121f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    Mutex::Autolock _l(mLock);
122f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    mInvalidate = true;
123f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    mCondition.signal();
124f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    return NO_ERROR;
125f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
126f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
127f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopianstatus_t MessageQueue::queueMessage(
128f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        const MessageList::NODE_PTR& message, nsecs_t relTime, uint32_t flags)
129f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
130f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    Mutex::Autolock _l(mLock);
131f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    message->when = systemTime() + relTime;
132f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    mMessages.insert(message);
133f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
134f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    //LOGD("MessageQueue::queueMessage time = %lld ms", message->when);
135f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    //dumpLocked(message);
136f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
137f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    mCondition.signal();
138f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    return NO_ERROR;
139f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
140f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
141f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopianvoid MessageQueue::dump(const MessageList::NODE_PTR& message)
142f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
143f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    Mutex::Autolock _l(mLock);
144f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    dumpLocked(message);
145f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
146f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
147f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopianvoid MessageQueue::dumpLocked(const MessageList::NODE_PTR& message)
148f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian{
149f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    MessageList::NODE_PTR l(mMessages.head());
150f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    int c = 0;
151f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    while (l != 0) {
152f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        const char tick = (l == message) ? '>' : ' ';
153f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        LOGD("%c %d: msg{.what=%08x, when=%lld}", tick, c, l->what, l->when);
154f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        l = l->getNext();
155f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian        c++;
156f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian    }
157f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}
158f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
159f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian// ---------------------------------------------------------------------------
160f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian
161f1d8e87b09abf963cd5b6a026194c1940fadb7b4Mathias Agopian}; // namespace android
162