Home | History | Annotate | Download | only in smoke
      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