1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #define LOG_TAG "MessageThread" 27 28 #include "config.h" 29 30 #include <sys/time.h> 31 #include <time.h> 32 33 #include "MessageThread.h" 34 #include "ScriptController.h" 35 36 #include <utils/Log.h> 37 38 namespace android { 39 40 static bool compareMessages(const Message& msg1, 41 const Message& msg2, 42 bool memberIsNull) { 43 return (msg1.object() == msg2.object() && 44 (memberIsNull || msg1.member() == msg2.member())); 45 } 46 47 bool MessageQueue::hasMessages(const Message& message) { 48 AutoMutex lock(m_mutex); 49 50 static const Message::GenericMemberFunction nullMember = NULL; 51 const bool memberIsNull = message.member() == nullMember; 52 53 for (list<Message*>::iterator it = m_messages.begin(); 54 it != m_messages.end(); ++it) { 55 Message* m = *it; 56 if (compareMessages(message, *m, memberIsNull)) 57 return true; 58 } 59 return false; 60 } 61 62 void MessageQueue::remove(const Message& message) { 63 AutoMutex lock(m_mutex); 64 65 static const Message::GenericMemberFunction nullMember = NULL; 66 const bool memberIsNull = message.member() == nullMember; 67 68 for (list<Message*>::iterator it = m_messages.begin(); 69 it != m_messages.end(); ++it) { 70 Message* m = *it; 71 if (compareMessages(message, *m, memberIsNull)) { 72 it = m_messages.erase(it); 73 delete m; 74 } 75 } 76 } 77 78 void MessageQueue::post(Message* message) { 79 AutoMutex lock(m_mutex); 80 81 double when = message->m_when; 82 ALOG_ASSERT(when > 0, "Message time may not be 0"); 83 84 list<Message*>::iterator it; 85 for (it = m_messages.begin(); it != m_messages.end(); ++it) { 86 Message* m = *it; 87 if (when < m->m_when) { 88 break; 89 } 90 } 91 m_messages.insert(it, message); 92 m_condition.signal(); 93 } 94 95 void MessageQueue::postAtFront(Message* message) { 96 AutoMutex lock(m_mutex); 97 message->m_when = 0; 98 m_messages.push_front(message); 99 } 100 101 Message* MessageQueue::next() { 102 AutoMutex lock(m_mutex); 103 while (true) { 104 if (m_messages.empty()) { 105 // No messages, wait until another arrives 106 m_condition.wait(m_mutex); 107 } 108 Message* next = m_messages.front(); 109 double now = WTF::currentTimeMS(); 110 double diff = next->m_when - now; 111 if (diff > 0) { 112 // Not time for this message yet, wait the difference in nanos 113 m_condition.waitRelative(m_mutex, 114 static_cast<nsecs_t>(diff * 1000000) /* nanos */); 115 } else { 116 // Time for this message to run. 117 m_messages.pop_front(); 118 return next; 119 } 120 } 121 } 122 123 bool MessageThread::threadLoop() { 124 WebCore::ScriptController::initializeThreading(); 125 126 while (true) { 127 Message* message = m_queue.next(); 128 if (message != NULL) { 129 message->run(); 130 } 131 } 132 return false; 133 } 134 135 // Global thread object obtained by messageThread(). 136 static sp<MessageThread> gMessageThread; 137 138 MessageThread* messageThread() { 139 if (gMessageThread == NULL) { 140 gMessageThread = new MessageThread(); 141 gMessageThread->run("WebCoreThread"); 142 } 143 return gMessageThread.get(); 144 } 145 146 } // namespace android 147