diff options
author | Patrick Scott <phanna@android.com> | 2010-06-16 11:34:35 -0400 |
---|---|---|
committer | Patrick Scott <phanna@android.com> | 2010-06-21 10:24:02 -0400 |
commit | 43fbbb2aa64694b5006656423cd74e4ab1e65fba (patch) | |
tree | 83fe63fd712aba9c94af739712ecd81c78209e41 /WebKit | |
parent | b94a30def72cdfa7401b9b0b960385e3a92afa94 (diff) | |
download | external_webkit-43fbbb2aa64694b5006656423cd74e4ab1e65fba.zip external_webkit-43fbbb2aa64694b5006656423cd74e4ab1e65fba.tar.gz external_webkit-43fbbb2aa64694b5006656423cd74e4ab1e65fba.tar.bz2 |
Initial messaging model for project 'smoke'
Not compiled yet as it is unused (without other patches). I wanted
to start getting something committed so Derek and I can work together
on the next part.
Change-Id: I5dba6107e572c9be402d75df49c3c69e2c527590
Diffstat (limited to 'WebKit')
-rw-r--r-- | WebKit/android/smoke/MessageThread.cpp | 146 | ||||
-rw-r--r-- | WebKit/android/smoke/MessageThread.h | 108 | ||||
-rw-r--r-- | WebKit/android/smoke/MessageTypes.h | 159 |
3 files changed, 413 insertions, 0 deletions
diff --git a/WebKit/android/smoke/MessageThread.cpp b/WebKit/android/smoke/MessageThread.cpp new file mode 100644 index 0000000..48f2222 --- /dev/null +++ b/WebKit/android/smoke/MessageThread.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "MessageThread" + +#include "config.h" + +#include <sys/time.h> +#include <time.h> + +#include "MessageThread.h" +#include "ScriptController.h" + +#include <utils/Log.h> + +namespace android { + +static bool compareMessages(const Message& msg1, + const Message& msg2, + bool memberIsNull) { + return (msg1.object() == msg2.object() && + (memberIsNull || msg1.member() == msg2.member())); +} + +bool MessageQueue::hasMessages(const Message& message) { + AutoMutex lock(m_mutex); + + static const Message::GenericMemberFunction nullMember = NULL; + const bool memberIsNull = message.member() == nullMember; + + for (list<Message*>::iterator it = m_messages.begin(); + it != m_messages.end(); ++it) { + Message* m = *it; + if (compareMessages(message, *m, memberIsNull)) + return true; + } + return false; +} + +void MessageQueue::remove(const Message& message) { + AutoMutex lock(m_mutex); + + static const Message::GenericMemberFunction nullMember = NULL; + const bool memberIsNull = message.member() == nullMember; + + for (list<Message*>::iterator it = m_messages.begin(); + it != m_messages.end(); ++it) { + Message* m = *it; + if (compareMessages(message, *m, memberIsNull)) { + it = m_messages.erase(it); + delete m; + } + } +} + +void MessageQueue::post(Message* message) { + AutoMutex lock(m_mutex); + + double when = message->m_when; + LOG_ASSERT(when > 0, "Message time may not be 0"); + + list<Message*>::iterator it; + for (it = m_messages.begin(); it != m_messages.end(); ++it) { + Message* m = *it; + if (when < m->m_when) { + break; + } + } + m_messages.insert(it, message); + m_condition.signal(); +} + +void MessageQueue::postAtFront(Message* message) { + AutoMutex lock(m_mutex); + message->m_when = 0; + m_messages.push_front(message); +} + +Message* MessageQueue::next() { + AutoMutex lock(m_mutex); + while (true) { + if (m_messages.empty()) { + // No messages, wait until another arrives + m_condition.wait(m_mutex); + } + Message* next = m_messages.front(); + double now = WTF::currentTimeMS(); + double diff = next->m_when - now; + if (diff > 0) { + // Not time for this message yet, wait the difference in nanos + m_condition.waitRelative(m_mutex, + static_cast<nsecs_t>(diff * 1000000) /* nanos */); + } else { + // Time for this message to run. + m_messages.pop_front(); + return next; + } + } +} + +bool MessageThread::threadLoop() { + WebCore::ScriptController::initializeThreading(); + + while (true) { + Message* message = m_queue.next(); + if (message != NULL) { + message->run(); + } + } + return false; +} + +// Global thread object obtained by messageThread(). +static sp<MessageThread> gMessageThread; + +MessageThread* messageThread() { + if (gMessageThread == NULL) { + gMessageThread = new MessageThread(); + gMessageThread->run("WebCoreThread"); + } + return gMessageThread.get(); +} + +} // namespace android diff --git a/WebKit/android/smoke/MessageThread.h b/WebKit/android/smoke/MessageThread.h new file mode 100644 index 0000000..ca0115b --- /dev/null +++ b/WebKit/android/smoke/MessageThread.h @@ -0,0 +1,108 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_WEBKIT_MESSAGETHREAD_H +#define ANDROID_WEBKIT_MESSAGETHREAD_H + +#include <list> + +#include "MessageTypes.h" + +#include <utils/threads.h> + +using std::list; + +namespace android { + +class MessageQueue { +public: + MessageQueue() {} + + // Return true if the queue has messages with the given object and member + // function. If member is null, return true if the message has the same + // object. + template <class T> + bool hasMessages(T* object, void (T::*member)(void)); + + // Remove all messages with the given object and member function. If + // member is null, remove all messages with the given object. + template <class T> + void remove(T* object, void (T::*member)(void)); + + // Post a new message to the queue. + void post(Message* closure); + + // Post a new message at the front of the queue. + void postAtFront(Message* closure); + + // Obtain the next message. Blocks until either a new message arrives or + // we reach the time of the next message. + Message* next(); + +private: + bool hasMessages(const Message& message); + void remove(const Message& message); + + list<Message*> m_messages; + Mutex m_mutex; + Condition m_condition; +}; + +template <class T> +bool MessageQueue::hasMessages(T* object, void (T::*member)(void)) { + MemberFunctionMessage<T, void> message(object, member); + return hasMessages(message); +} + +template <class T> +void MessageQueue::remove(T* object, void (T::*member)(void)) { + MemberFunctionMessage<T, void> message(object, member); + remove(message); +} + +class MessageThread : public Thread { +public: + MessageQueue& queue() { return m_queue; } + +private: + MessageThread() : Thread(true /* canCallJava */) {} + + virtual bool threadLoop(); + + MessageQueue m_queue; + // Used for thread initialization + Mutex m_mutex; + Condition m_condition; + + friend MessageThread* messageThread(); +}; + +// Get (possibly creating) the global MessageThread object used to pass +// messages to WebCore. +MessageThread* messageThread(); + +} // namespace android + +#endif // ANDROID_WEBKIT_MESSAGETHREAD_H diff --git a/WebKit/android/smoke/MessageTypes.h b/WebKit/android/smoke/MessageTypes.h new file mode 100644 index 0000000..7da6cb8 --- /dev/null +++ b/WebKit/android/smoke/MessageTypes.h @@ -0,0 +1,159 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_WEBKIT_MESSAGETYPES_H_ +#define ANDROID_WEBKIT_MESSAGETYPES_H_ + +#include <wtf/CurrentTime.h> + +// TODO(phanna): autogenerate these types! + +namespace android { + +// Forward declared for friendship! +class MessageQueue; + +// Removes the reference from the typename so we store the actual value in the +// closure. +template <typename T> struct remove_reference { typedef T type; }; +template <typename T> struct remove_reference<T&> { typedef T type; }; + +// Prevent the compiler from inferring the type. +template <typename T> struct identity { typedef T type; }; + +// Message base class. Defines the public run() method and contains generic +// object and member function variables for use in MessageQueue. +// +// Note: The template subclass MemberFunctionMessage casts its object and +// member function to the generic void* and Message::* types. During run(), +// each template specialization downcasts to the original type and invokes the +// correct function. This may seem dangerous but the compiler enforces +// correctness in NewMessage and in the template constructor. +class Message { +public: + typedef void (Message::*GenericMemberFunction)(void); + + virtual ~Message() {} + virtual void run() = 0; + + // The wall time that the message is supposed to run. + double m_when; + + void* object() const { return m_object; } + GenericMemberFunction member() const { return m_member; } + +protected: + Message(void* object, GenericMemberFunction member, long delay = 0) + : m_object(object) + , m_member(member) { + m_when = WTF::currentTimeMS() + delay; + } + + // Downcast back to the original template params in run(). Also accessed + // by MessageQueue to compare messages. + void* m_object; + GenericMemberFunction m_member; + +private: + // Disallow copy + Message(const Message&); +}; + +// Forward declaration for partial specialization. +template <class T, typename A1> +class MemberFunctionMessage; + +template <class T> +class MemberFunctionMessage<T, void> : public Message { +private: + typedef void (T::*MemberSignature)(); + +public: + inline MemberFunctionMessage(T* object, + MemberSignature member, + long delay = 0) + : Message(reinterpret_cast<void*>(object), + reinterpret_cast<GenericMemberFunction>(member), + delay) {} + + virtual void run() { + MemberSignature member = reinterpret_cast<MemberSignature>(m_member); + (reinterpret_cast<T*>(m_object)->*member)(); + delete this; + } +}; + +template <class T> +inline Message* NewMessage(T* object, void (T::*member)()) { + return new MemberFunctionMessage<T, void>(object, member); +} + +template <class T> +inline Message* NewDelayedMessage(T* object, void (T::*member)(), long delay) { + return new MemberFunctionMessage<T, void>(object, member, delay); +} + +template <class T, typename A1> +class MemberFunctionMessage : public Message { +private: + typedef void (T::*MemberSignature)(A1); + +public: + inline MemberFunctionMessage(T* object, + MemberSignature member, + A1 arg1, + long delay = 0) + : Message(reinterpret_cast<void*>(object), + reinterpret_cast<GenericMemberFunction>(member), + delay) + , m_arg1(arg1) {} + + virtual void run() { + MemberSignature member = reinterpret_cast<MemberSignature>(m_member); + (reinterpret_cast<T*>(m_object)->*member)(m_arg1); + delete this; + } + +private: + typename remove_reference<A1>::type m_arg1; +}; + +template <class T, typename A1> +inline Message* NewMessage(T* object, void (T::*member)(A1), + typename identity<A1>::type arg1) { + return new MemberFunctionMessage<T, A1>( + object, member, arg1); +} + +template <class T, typename A1> +inline Message* NewDelayedMessage(T* object, void (T::*member)(A1), + typename identity<A1>::type arg1, long delay) { + return new MemberFunctionMessage<T, A1>(object, member, arg1, delay); +} + +} // namespace android + + +#endif // ANDROID_WEBKIT_MESSAGETYPES_H_ |