MessageQueue.h revision f1d8e87b09abf963cd5b6a026194c1940fadb7b4
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ANDROID_MESSAGE_QUEUE_H 18#define ANDROID_MESSAGE_QUEUE_H 19 20#include <stdint.h> 21#include <errno.h> 22#include <sys/types.h> 23 24#include <utils/threads.h> 25#include <utils/Timers.h> 26 27 28namespace android { 29 30// --------------------------------------------------------------------------- 31 32template<typename NODE_PTR_TYPE> 33class DoublyLinkedList 34{ 35protected: 36 typedef NODE_PTR_TYPE NODE_PTR; 37 38 NODE_PTR mFirst; 39 NODE_PTR mLast; 40 41public: 42 class Node { 43 friend class DoublyLinkedList; 44 mutable NODE_PTR next; 45 mutable NODE_PTR prev; 46 public: 47 typedef NODE_PTR PTR; 48 inline NODE_PTR getNext() const { return next; } 49 inline NODE_PTR getPrev() const { return prev; } 50 void detach() { 51 prev = 0; 52 next = 0; 53 } 54 }; 55 56 DoublyLinkedList() : mFirst(0), mLast(0) { } 57 ~DoublyLinkedList() { } 58 59 bool isEmpty() const { return mFirst == 0; } 60 const NODE_PTR& head() const { return mFirst; } 61 const NODE_PTR& tail() const { return mLast; } 62 const NODE_PTR& head() { return mFirst; } 63 const NODE_PTR& tail() { return mLast; } 64 65 void insertAfter(const NODE_PTR& node, const NODE_PTR& newNode) { 66 newNode->prev = node; 67 newNode->next = node->next; 68 if (node->next == 0) mLast = newNode; 69 else node->next->prev = newNode; 70 node->next = newNode; 71 } 72 73 void insertBefore(const NODE_PTR& node, const NODE_PTR& newNode) { 74 newNode->prev = node->prev; 75 newNode->next = node; 76 if (node->prev == 0) mFirst = newNode; 77 else node->prev->next = newNode; 78 node->prev = newNode; 79 } 80 81 void insertHead(const NODE_PTR& newNode) { 82 if (mFirst == 0) { 83 mFirst = mLast = newNode; 84 newNode->prev = newNode->next = 0; 85 } else { 86 newNode->prev = 0; 87 newNode->next = mFirst; 88 mFirst->prev = newNode; 89 mFirst = newNode; 90 } 91 } 92 93 void insertTail(const NODE_PTR& newNode) { 94 if (mLast == 0) { 95 insertHead(newNode); 96 } else { 97 newNode->prev = mLast; 98 newNode->next = 0; 99 mLast->next = newNode; 100 mLast = newNode; 101 } 102 } 103 104 NODE_PTR remove(const NODE_PTR& node) { 105 if (node->prev == 0) mFirst = node->next; 106 else node->prev->next = node->next; 107 if (node->next == 0) mLast = node->prev; 108 else node->next->prev = node->prev; 109 return node; 110 } 111}; 112 113// --------------------------------------------------------------------------- 114 115template<typename NODE_PTR_TYPE> 116class SortedList : protected DoublyLinkedList< NODE_PTR_TYPE > 117{ 118 typedef DoublyLinkedList< NODE_PTR_TYPE > forward; 119public: 120 typedef NODE_PTR_TYPE NODE_PTR; 121 inline bool isEmpty() const { return forward::isEmpty(); } 122 inline const NODE_PTR& head() const { return forward::head(); } 123 inline const NODE_PTR& tail() const { return forward::tail(); } 124 inline const NODE_PTR& head() { return forward::head(); } 125 inline const NODE_PTR& tail() { return forward::tail(); } 126 inline NODE_PTR remove(const NODE_PTR& node) { return forward::remove(node); } 127 void insert(const NODE_PTR& node) { 128 NODE_PTR l(head()); 129 while (l != 0) { 130 if (*node < *l) { 131 insertBefore(l, node); 132 return; 133 } 134 l = l->getNext(); 135 } 136 insertTail(node); 137 } 138}; 139 140// ============================================================================ 141 142class MessageBase : 143 public LightRefBase<MessageBase>, 144 public DoublyLinkedList< sp<MessageBase> >::Node 145{ 146public: 147 nsecs_t when; 148 uint32_t what; 149 int32_t arg0; 150 151 MessageBase(uint32_t what=0, int32_t arg0=0) 152 : when(0), what(what), arg0(arg0) { } 153 154 // return true if message has a handler 155 virtual bool handler() { return false; } 156 157protected: 158 virtual ~MessageBase() { } 159 160private: 161 friend class LightRefBase<MessageBase>; 162}; 163 164inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { 165 return lhs.when < rhs.when; 166} 167 168// --------------------------------------------------------------------------- 169 170/* 171 * MessageList is a sorted list of sp<MessageBase> 172 */ 173 174typedef SortedList< MessageBase::Node::PTR > MessageList; 175 176// --------------------------------------------------------------------------- 177 178class MessageQueue 179{ 180public: 181 182 // this is a work-around the multichar constant warning. A macro would 183 // work too, but would pollute the namespace. 184 template <int a, int b, int c, int d> 185 struct WHAT { 186 static const uint32_t Value = 187 (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)| 188 (uint32_t(c&0xff)<<8)|uint32_t(d&0xff); 189 }; 190 191 MessageQueue(); 192 ~MessageQueue(); 193 194 // pre-defined messages 195 enum { 196 INVALIDATE = WHAT<'_','p','d','t'>::Value 197 }; 198 199 MessageList::NODE_PTR waitMessage(nsecs_t timeout = -1); 200 201 status_t postMessage(const MessageList::NODE_PTR& message, 202 nsecs_t reltime=0, uint32_t flags = 0); 203 204 status_t invalidate(); 205 206 void dump(const MessageList::NODE_PTR& message); 207 208private: 209 status_t queueMessage(const MessageList::NODE_PTR& message, 210 nsecs_t reltime, uint32_t flags); 211 void dumpLocked(const MessageList::NODE_PTR& message); 212 213 Mutex mLock; 214 Condition mCondition; 215 MessageList mMessages; 216 bool mInvalidate; 217 MessageList::NODE_PTR mInvalidateMessage; 218}; 219 220// --------------------------------------------------------------------------- 221 222}; // namespace android 223 224#endif /* ANDROID_MESSAGE_QUEUE_H */ 225