summaryrefslogtreecommitdiffstats
path: root/WebKit
diff options
context:
space:
mode:
authorPatrick Scott <phanna@android.com>2010-06-16 11:34:35 -0400
committerPatrick Scott <phanna@android.com>2010-06-21 10:24:02 -0400
commit43fbbb2aa64694b5006656423cd74e4ab1e65fba (patch)
tree83fe63fd712aba9c94af739712ecd81c78209e41 /WebKit
parentb94a30def72cdfa7401b9b0b960385e3a92afa94 (diff)
downloadexternal_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.cpp146
-rw-r--r--WebKit/android/smoke/MessageThread.h108
-rw-r--r--WebKit/android/smoke/MessageTypes.h159
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_