Looper.h revision 1ea51bf519bdfc0e04daa88b8788f06105c5599b
1/* 2 * Copyright (C) 2010 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 UTILS_LOOPER_H 18#define UTILS_LOOPER_H 19 20#include <utils/threads.h> 21#include <utils/RefBase.h> 22#include <utils/KeyedVector.h> 23#include <utils/Timers.h> 24 25#include <android/looper.h> 26 27// When defined, uses epoll_wait() for polling, otherwise uses poll(). 28#define LOOPER_USES_EPOLL 29 30#ifdef LOOPER_USES_EPOLL 31#include <sys/epoll.h> 32#else 33#include <sys/poll.h> 34#endif 35 36/* 37 * Declare a concrete type for the NDK's looper forward declaration. 38 */ 39struct ALooper { 40}; 41 42namespace android { 43 44/** 45 * A message that can be posted to a Looper. 46 */ 47struct Message { 48 Message() : what(0) { } 49 Message(int what) : what(what) { } 50 51 /* The message type. (interpretation is left up to the handler) */ 52 int what; 53}; 54 55 56/** 57 * Interface for a Looper message handler. 58 * 59 * The Looper holds a strong reference to the message handler whenever it has 60 * a message to deliver to it. Make sure to call Looper::removeMessages 61 * to remove any pending messages destined for the handler so that the handler 62 * can be destroyed. 63 */ 64class MessageHandler : public virtual RefBase { 65protected: 66 virtual ~MessageHandler() { } 67 68public: 69 /** 70 * Handles a message. 71 */ 72 virtual void handleMessage(const Message& message) = 0; 73}; 74 75 76/** 77 * A simple proxy that holds a weak reference to a message handler. 78 */ 79class WeakMessageHandler : public MessageHandler { 80public: 81 WeakMessageHandler(const wp<MessageHandler>& handler); 82 virtual void handleMessage(const Message& message); 83 84private: 85 wp<MessageHandler> mHandler; 86}; 87 88 89/** 90 * A polling loop that supports monitoring file descriptor events, optionally 91 * using callbacks. The implementation uses epoll() internally. 92 * 93 * A looper can be associated with a thread although there is no requirement that it must be. 94 */ 95class Looper : public ALooper, public RefBase { 96protected: 97 virtual ~Looper(); 98 99public: 100 /** 101 * Creates a looper. 102 * 103 * If allowNonCallbaks is true, the looper will allow file descriptors to be 104 * registered without associated callbacks. This assumes that the caller of 105 * pollOnce() is prepared to handle callback-less events itself. 106 */ 107 Looper(bool allowNonCallbacks); 108 109 /** 110 * Returns whether this looper instance allows the registration of file descriptors 111 * using identifiers instead of callbacks. 112 */ 113 bool getAllowNonCallbacks() const; 114 115 /** 116 * Waits for events to be available, with optional timeout in milliseconds. 117 * Invokes callbacks for all file descriptors on which an event occurred. 118 * 119 * If the timeout is zero, returns immediately without blocking. 120 * If the timeout is negative, waits indefinitely until an event appears. 121 * 122 * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before 123 * the timeout expired and no callbacks were invoked and no other file 124 * descriptors were ready. 125 * 126 * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. 127 * 128 * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given 129 * timeout expired. 130 * 131 * Returns ALOOPER_POLL_ERROR if an error occurred. 132 * 133 * Returns a value >= 0 containing an identifier if its file descriptor has data 134 * and it has no callback function (requiring the caller here to handle it). 135 * In this (and only this) case outFd, outEvents and outData will contain the poll 136 * events and data associated with the fd, otherwise they will be set to NULL. 137 * 138 * This method does not return until it has finished invoking the appropriate callbacks 139 * for all file descriptors that were signalled. 140 */ 141 int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData); 142 inline int pollOnce(int timeoutMillis) { 143 return pollOnce(timeoutMillis, NULL, NULL, NULL); 144 } 145 146 /** 147 * Like pollOnce(), but performs all pending callbacks until all 148 * data has been consumed or a file descriptor is available with no callback. 149 * This function will never return ALOOPER_POLL_CALLBACK. 150 */ 151 int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData); 152 inline int pollAll(int timeoutMillis) { 153 return pollAll(timeoutMillis, NULL, NULL, NULL); 154 } 155 156 /** 157 * Wakes the poll asynchronously. 158 * 159 * This method can be called on any thread. 160 * This method returns immediately. 161 */ 162 void wake(); 163 164 /** 165 * Adds a new file descriptor to be polled by the looper. 166 * If the same file descriptor was previously added, it is replaced. 167 * 168 * "fd" is the file descriptor to be added. 169 * "ident" is an identifier for this event, which is returned from ALooper_pollOnce(). 170 * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback. 171 * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT. 172 * "callback" is the function to call when there is an event on the file descriptor. 173 * "data" is a private data pointer to supply to the callback. 174 * 175 * There are two main uses of this function: 176 * 177 * (1) If "callback" is non-NULL, then this function will be called when there is 178 * data on the file descriptor. It should execute any events it has pending, 179 * appropriately reading from the file descriptor. The 'ident' is ignored in this case. 180 * 181 * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce 182 * when its file descriptor has data available, requiring the caller to take 183 * care of processing it. 184 * 185 * Returns 1 if the file descriptor was added, 0 if the arguments were invalid. 186 * 187 * This method can be called on any thread. 188 * This method may block briefly if it needs to wake the poll. 189 */ 190 int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data); 191 192 /** 193 * Removes a previously added file descriptor from the looper. 194 * 195 * When this method returns, it is safe to close the file descriptor since the looper 196 * will no longer have a reference to it. However, it is possible for the callback to 197 * already be running or for it to run one last time if the file descriptor was already 198 * signalled. Calling code is responsible for ensuring that this case is safely handled. 199 * For example, if the callback takes care of removing itself during its own execution either 200 * by returning 0 or by calling this method, then it can be guaranteed to not be invoked 201 * again at any later time unless registered anew. 202 * 203 * Returns 1 if the file descriptor was removed, 0 if none was previously registered. 204 * 205 * This method can be called on any thread. 206 * This method may block briefly if it needs to wake the poll. 207 */ 208 int removeFd(int fd); 209 210 /** 211 * Enqueues a message to be processed by the specified handler. 212 * 213 * The handler must not be null. 214 * This method can be called on any thread. 215 */ 216 void sendMessage(const sp<MessageHandler>& handler, const Message& message); 217 218 /** 219 * Enqueues a message to be processed by the specified handler after all pending messages 220 * after the specified delay. 221 * 222 * The time delay is specified in uptime nanoseconds. 223 * The handler must not be null. 224 * This method can be called on any thread. 225 */ 226 void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler, 227 const Message& message); 228 229 /** 230 * Enqueues a message to be processed by the specified handler after all pending messages 231 * at the specified time. 232 * 233 * The time is specified in uptime nanoseconds. 234 * The handler must not be null. 235 * This method can be called on any thread. 236 */ 237 void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler, 238 const Message& message); 239 240 /** 241 * Removes all messages for the specified handler from the queue. 242 * 243 * The handler must not be null. 244 * This method can be called on any thread. 245 */ 246 void removeMessages(const sp<MessageHandler>& handler); 247 248 /** 249 * Removes all messages of a particular type for the specified handler from the queue. 250 * 251 * The handler must not be null. 252 * This method can be called on any thread. 253 */ 254 void removeMessages(const sp<MessageHandler>& handler, int what); 255 256 /** 257 * Prepares a looper associated with the calling thread, and returns it. 258 * If the thread already has a looper, it is returned. Otherwise, a new 259 * one is created, associated with the thread, and returned. 260 * 261 * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0. 262 */ 263 static sp<Looper> prepare(int opts); 264 265 /** 266 * Sets the given looper to be associated with the calling thread. 267 * If another looper is already associated with the thread, it is replaced. 268 * 269 * If "looper" is NULL, removes the currently associated looper. 270 */ 271 static void setForThread(const sp<Looper>& looper); 272 273 /** 274 * Returns the looper associated with the calling thread, or NULL if 275 * there is not one. 276 */ 277 static sp<Looper> getForThread(); 278 279private: 280 struct Request { 281 int fd; 282 int ident; 283 ALooper_callbackFunc callback; 284 void* data; 285 }; 286 287 struct Response { 288 int events; 289 Request request; 290 }; 291 292 struct MessageEnvelope { 293 MessageEnvelope() : uptime(0) { } 294 295 MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler, 296 const Message& message) : uptime(uptime), handler(handler), message(message) { 297 } 298 299 nsecs_t uptime; 300 sp<MessageHandler> handler; 301 Message message; 302 }; 303 304 const bool mAllowNonCallbacks; // immutable 305 306 int mWakeReadPipeFd; // immutable 307 int mWakeWritePipeFd; // immutable 308 Mutex mLock; 309 310 Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock 311 bool mSendingMessage; // guarded by mLock 312 313#ifdef LOOPER_USES_EPOLL 314 int mEpollFd; // immutable 315 316 // Locked list of file descriptor monitoring requests. 317 KeyedVector<int, Request> mRequests; // guarded by mLock 318#else 319 // The lock guards state used to track whether there is a poll() in progress and whether 320 // there are any other threads waiting in wakeAndLock(). The condition variables 321 // are used to transfer control among these threads such that all waiters are 322 // serviced before a new poll can begin. 323 // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake 324 // until mPolling becomes false, then decrements mWaiters again. 325 // The poll() method blocks on mResume until mWaiters becomes 0, then sets 326 // mPolling to true, blocks until the poll completes, then resets mPolling to false 327 // and signals mResume if there are waiters. 328 bool mPolling; // guarded by mLock 329 uint32_t mWaiters; // guarded by mLock 330 Condition mAwake; // guarded by mLock 331 Condition mResume; // guarded by mLock 332 333 Vector<struct pollfd> mRequestedFds; // must hold mLock and mPolling must be false to modify 334 Vector<Request> mRequests; // must hold mLock and mPolling must be false to modify 335 336 ssize_t getRequestIndexLocked(int fd); 337 void wakeAndLock(); 338#endif 339 340 // This state is only used privately by pollOnce and does not require a lock since 341 // it runs on a single thread. 342 Vector<Response> mResponses; 343 size_t mResponseIndex; 344 nsecs_t mNextMessageUptime; // set to LLONG_MAX when none 345 346 int pollInner(int timeoutMillis); 347 void awoken(); 348 void pushResponse(int events, const Request& request); 349 350 static void initTLSKey(); 351 static void threadDestructor(void *st); 352}; 353 354} // namespace android 355 356#endif // UTILS_LOOPER_H 357