ALooper.cpp revision 72961230a5890071bcca436eb5630172ce84ec41
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//#define LOG_NDEBUG 0 18#define LOG_TAG "ALooper" 19#include <utils/Log.h> 20 21#include <sys/time.h> 22 23#include "ALooper.h" 24 25#include "AHandler.h" 26#include "ALooperRoster.h" 27#include "AMessage.h" 28 29namespace android { 30 31ALooperRoster gLooperRoster; 32 33struct ALooper::LooperThread : public Thread { 34 LooperThread(ALooper *looper) 35 : mLooper(looper) { 36 } 37 38 virtual bool threadLoop() { 39 return mLooper->loop(); 40 } 41 42protected: 43 virtual ~LooperThread() {} 44 45private: 46 ALooper *mLooper; 47 48 DISALLOW_EVIL_CONSTRUCTORS(LooperThread); 49}; 50 51// static 52int64_t ALooper::GetNowUs() { 53 struct timeval tv; 54 gettimeofday(&tv, NULL); 55 56 return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec; 57} 58 59ALooper::ALooper() 60 : mRunningLocally(false) { 61} 62 63ALooper::~ALooper() { 64 stop(); 65} 66 67ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) { 68 return gLooperRoster.registerHandler(this, handler); 69} 70 71void ALooper::unregisterHandler(handler_id handlerID) { 72 gLooperRoster.unregisterHandler(handlerID); 73} 74 75status_t ALooper::start(bool runOnCallingThread) { 76 if (runOnCallingThread) { 77 { 78 Mutex::Autolock autoLock(mLock); 79 80 if (mThread != NULL || mRunningLocally) { 81 return INVALID_OPERATION; 82 } 83 84 mRunningLocally = true; 85 } 86 87 do { 88 } while (loop()); 89 90 return OK; 91 } 92 93 Mutex::Autolock autoLock(mLock); 94 95 if (mThread != NULL || mRunningLocally) { 96 return INVALID_OPERATION; 97 } 98 99 mThread = new LooperThread(this); 100 101 status_t err = mThread->run("ALooper"); 102 if (err != OK) { 103 mThread.clear(); 104 } 105 106 return err; 107} 108 109status_t ALooper::stop() { 110 sp<LooperThread> thread; 111 bool runningLocally; 112 113 { 114 Mutex::Autolock autoLock(mLock); 115 116 thread = mThread; 117 runningLocally = mRunningLocally; 118 mThread.clear(); 119 mRunningLocally = false; 120 } 121 122 if (thread == NULL && !runningLocally) { 123 return INVALID_OPERATION; 124 } 125 126 if (thread != NULL) { 127 thread->requestExit(); 128 } 129 130 mQueueChangedCondition.signal(); 131 132 if (!runningLocally) { 133 thread->requestExitAndWait(); 134 } 135 136 return OK; 137} 138 139void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) { 140 Mutex::Autolock autoLock(mLock); 141 142 int64_t whenUs; 143 if (delayUs > 0) { 144 whenUs = GetNowUs() + delayUs; 145 } else { 146 whenUs = GetNowUs(); 147 } 148 149 List<Event>::iterator it = mEventQueue.begin(); 150 while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) { 151 ++it; 152 } 153 154 Event event; 155 event.mWhenUs = whenUs; 156 event.mMessage = msg; 157 158 if (it == mEventQueue.begin()) { 159 mQueueChangedCondition.signal(); 160 } 161 162 mEventQueue.insert(it, event); 163} 164 165bool ALooper::loop() { 166 Event event; 167 168 { 169 Mutex::Autolock autoLock(mLock); 170 if (mThread == NULL && !mRunningLocally) { 171 return false; 172 } 173 if (mEventQueue.empty()) { 174 mQueueChangedCondition.wait(mLock); 175 return true; 176 } 177 int64_t whenUs = (*mEventQueue.begin()).mWhenUs; 178 int64_t nowUs = GetNowUs(); 179 180 if (whenUs > nowUs) { 181 int64_t delayUs = whenUs - nowUs; 182 mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll); 183 184 return true; 185 } 186 187 event = *mEventQueue.begin(); 188 mEventQueue.erase(mEventQueue.begin()); 189 } 190 191 gLooperRoster.deliverMessage(event.mMessage); 192 193 return true; 194} 195 196} // namespace android 197