Title: [86838] trunk/Source/WebCore
Revision
86838
Author
[email protected]
Date
2011-05-19 05:03:58 -0700 (Thu, 19 May 2011)

Log Message

2011-05-19  David Grogan  <[email protected]>

        Reviewed by David Levin.

        Make EventQueue post a Task to the task queue for each asynchronous event
        https://bugs.webkit.org/show_bug.cgi?id=60790

        Currently EventQueue queues up events to be fired asynchronously and
        fires each of them when a single DOMTimer goes off.  In the words of
        dimich, "Having 2 queues will sooner or later cause problems with
        ordering of tasks, termination, suspension and other things that all
        require some control on how queues operate."

        No new tests; this is just a refactoring to avoid potential future
        problems.

        * dom/EventQueue.cpp:
        (WebCore::EventQueue::EventQueue):
        (WebCore::EventQueue::EventDispatcherTask::create):
        (WebCore::EventQueue::EventDispatcherTask::dispatchEvent):
        (WebCore::EventQueue::EventDispatcherTask::performTask):
        (WebCore::EventQueue::EventDispatcherTask::cancel):
        (WebCore::EventQueue::EventDispatcherTask::EventDispatcherTask):
        (WebCore::EventQueue::removeEvent):
        (WebCore::EventQueue::enqueueEvent):
        (WebCore::EventQueue::enqueueOrDispatchScrollEvent):
        (WebCore::EventQueue::cancelEvent):
        (WebCore::EventQueue::cancelQueuedEvents):
        * dom/EventQueue.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (86837 => 86838)


--- trunk/Source/WebCore/ChangeLog	2011-05-19 11:47:02 UTC (rev 86837)
+++ trunk/Source/WebCore/ChangeLog	2011-05-19 12:03:58 UTC (rev 86838)
@@ -1,3 +1,33 @@
+2011-05-19  David Grogan  <[email protected]>
+
+        Reviewed by David Levin.
+
+        Make EventQueue post a Task to the task queue for each asynchronous event
+        https://bugs.webkit.org/show_bug.cgi?id=60790
+
+        Currently EventQueue queues up events to be fired asynchronously and
+        fires each of them when a single DOMTimer goes off.  In the words of
+        dimich, "Having 2 queues will sooner or later cause problems with
+        ordering of tasks, termination, suspension and other things that all
+        require some control on how queues operate."
+
+        No new tests; this is just a refactoring to avoid potential future
+        problems.
+
+        * dom/EventQueue.cpp:
+        (WebCore::EventQueue::EventQueue):
+        (WebCore::EventQueue::EventDispatcherTask::create):
+        (WebCore::EventQueue::EventDispatcherTask::dispatchEvent):
+        (WebCore::EventQueue::EventDispatcherTask::performTask):
+        (WebCore::EventQueue::EventDispatcherTask::cancel):
+        (WebCore::EventQueue::EventDispatcherTask::EventDispatcherTask):
+        (WebCore::EventQueue::removeEvent):
+        (WebCore::EventQueue::enqueueEvent):
+        (WebCore::EventQueue::enqueueOrDispatchScrollEvent):
+        (WebCore::EventQueue::cancelEvent):
+        (WebCore::EventQueue::cancelQueuedEvents):
+        * dom/EventQueue.h:
+
 2011-05-18  Yury Semikhatsky  <[email protected]>
 
         Reviewed by Pavel Feldman.

Modified: trunk/Source/WebCore/dom/Document.h (86837 => 86838)


--- trunk/Source/WebCore/dom/Document.h	2011-05-19 11:47:02 UTC (rev 86837)
+++ trunk/Source/WebCore/dom/Document.h	2011-05-19 12:03:58 UTC (rev 86838)
@@ -1374,7 +1374,7 @@
 
     bool m_usingGeolocation;
 
-    RefPtr<EventQueue> m_eventQueue;
+    OwnPtr<EventQueue> m_eventQueue;
 
     RefPtr<DocumentWeakReference> m_weakReference;
 

Modified: trunk/Source/WebCore/dom/EventQueue.cpp (86837 => 86838)


--- trunk/Source/WebCore/dom/EventQueue.cpp	2011-05-19 11:47:02 UTC (rev 86837)
+++ trunk/Source/WebCore/dom/EventQueue.cpp	2011-05-19 12:03:58 UTC (rev 86838)
@@ -33,7 +33,6 @@
 #include "EventNames.h"
 #include "RuntimeApplicationChecks.h"
 #include "ScriptExecutionContext.h"
-#include "SuspendableTimer.h"
 
 namespace WebCore {
     
@@ -43,42 +42,79 @@
     return applicationIsSafari() && (document->url().protocolIs("feed") || document->url().protocolIs("feeds"));
 }
 
-class EventQueueTimer : public SuspendableTimer {
-    WTF_MAKE_NONCOPYABLE(EventQueueTimer);
-public:
-    EventQueueTimer(EventQueue* eventQueue, ScriptExecutionContext* context)
-        : SuspendableTimer(context)
-        , m_eventQueue(eventQueue) { }
-
-private:
-    virtual void fired() { m_eventQueue->pendingEventTimerFired(); }
-    EventQueue* m_eventQueue;    
-};
-
-PassRefPtr<EventQueue> EventQueue::create(ScriptExecutionContext* context)
+PassOwnPtr<EventQueue> EventQueue::create(ScriptExecutionContext* context)
 {
-    return adoptRef(new EventQueue(context));
+    return adoptPtr(new EventQueue(context));
 }
 
 EventQueue::EventQueue(ScriptExecutionContext* context)
-    : m_pendingEventTimer(adoptPtr(new EventQueueTimer(this, context)))
+    : m_scriptExecutionContext(context)
 {
 }
 
 EventQueue::~EventQueue()
 {
+    cancelQueuedEvents();
 }
 
-void EventQueue::enqueueEvent(PassRefPtr<Event> event)
+class EventQueue::EventDispatcherTask : public ScriptExecutionContext::Task {
+public:
+    static PassOwnPtr<EventDispatcherTask> create(PassRefPtr<Event> event, EventQueue* eventQueue)
+    {
+        return adoptPtr(new EventDispatcherTask(event, eventQueue));
+    }
+
+    void dispatchEvent(ScriptExecutionContext*, PassRefPtr<Event> event)
+    {
+        EventTarget* eventTarget = event->target();
+        if (eventTarget->toDOMWindow())
+            eventTarget->toDOMWindow()->dispatchEvent(event, 0);
+        else
+            eventTarget->dispatchEvent(event);
+    }
+
+    virtual void performTask(ScriptExecutionContext* context)
+    {
+        if (m_isCancelled)
+            return;
+        m_eventQueue->removeEvent(m_event.get());
+        dispatchEvent(context, m_event);
+    }
+
+    void cancel()
+    {
+        m_isCancelled = true;
+        m_event.clear();
+    }
+
+private:
+    EventDispatcherTask(PassRefPtr<Event> event, EventQueue* eventQueue)
+        : m_event(event)
+        , m_eventQueue(eventQueue)
+        , m_isCancelled(false)
+    {
+    }
+
+    RefPtr<Event> m_event;
+    EventQueue* m_eventQueue;
+    bool m_isCancelled;
+};
+
+void EventQueue::removeEvent(Event* event)
 {
-    ASSERT(event->target());
-    bool wasAdded = m_queuedEvents.add(event).second;
-    ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
-    
-    if (!m_pendingEventTimer->isActive())
-        m_pendingEventTimer->startOneShot(0);
+    if (Node* node = event->target()->toNode())
+        m_nodesWithQueuedScrollEvents.remove(node);
+    m_eventTaskMap.remove(event);
 }
 
+void EventQueue::enqueueEvent(PassRefPtr<Event> prpEvent)
+{
+    RefPtr<Event> event = prpEvent;
+    OwnPtr<EventDispatcherTask> task = EventDispatcherTask::create(event, this);
+    m_eventTaskMap.add(event.release(), task.get());
+    m_scriptExecutionContext->postTask(task.release());
+}
+
 void EventQueue::enqueueOrDispatchScrollEvent(PassRefPtr<Node> target, ScrollEventTargetType targetType)
 {
     // Per the W3C CSSOM View Module, scroll events fired at the document should bubble, others should not.
@@ -99,50 +135,22 @@
 
 bool EventQueue::cancelEvent(Event* event)
 {
-    bool found = m_queuedEvents.contains(event);
-    m_queuedEvents.remove(event);
-    if (m_queuedEvents.isEmpty())
-        m_pendingEventTimer->stop();
-    return found;
+    EventDispatcherTask* task = m_eventTaskMap.get(event);
+    if (!task)
+        return false;
+    task->cancel();
+    removeEvent(event);
+    return true;
 }
 
 void EventQueue::cancelQueuedEvents()
 {
-    m_pendingEventTimer->stop();
-    m_queuedEvents.clear();
-}
-
-void EventQueue::pendingEventTimerFired()
-{
-    ASSERT(!m_pendingEventTimer->isActive());
-    ASSERT(!m_queuedEvents.isEmpty());
-
+    for (EventTaskMap::iterator it = m_eventTaskMap.begin(); it != m_eventTaskMap.end(); ++it) {
+        EventDispatcherTask* task = it->second;
+        task->cancel();
+    }
+    m_eventTaskMap.clear();
     m_nodesWithQueuedScrollEvents.clear();
-
-    // Insert a marker for where we should stop.
-    ASSERT(!m_queuedEvents.contains(0));
-    bool wasAdded = m_queuedEvents.add(0).second;
-    ASSERT_UNUSED(wasAdded, wasAdded); // It should not have already been in the list.
-
-    RefPtr<EventQueue> protector(this);
-
-    while (!m_queuedEvents.isEmpty()) {
-        ListHashSet<RefPtr<Event> >::iterator iter = m_queuedEvents.begin();
-        RefPtr<Event> event = *iter;
-        m_queuedEvents.remove(iter);
-        if (!event)
-            break;
-        dispatchEvent(event.get());
-    }
 }
 
-void EventQueue::dispatchEvent(PassRefPtr<Event> event)
-{
-    EventTarget* eventTarget = event->target();
-    if (eventTarget->toDOMWindow())
-        eventTarget->toDOMWindow()->dispatchEvent(event, 0);
-    else
-        eventTarget->dispatchEvent(event);
 }
-
-}

Modified: trunk/Source/WebCore/dom/EventQueue.h (86837 => 86838)


--- trunk/Source/WebCore/dom/EventQueue.h	2011-05-19 11:47:02 UTC (rev 86837)
+++ trunk/Source/WebCore/dom/EventQueue.h	2011-05-19 12:03:58 UTC (rev 86838)
@@ -27,27 +27,24 @@
 #ifndef EventQueue_h
 #define EventQueue_h
 
+#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
-#include <wtf/ListHashSet.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
 
 class Event;
-class EventQueueTimer;
 class Node;
 class ScriptExecutionContext;
 
-class EventQueue : public RefCounted<EventQueue> {
+class EventQueue {
 public:
     enum ScrollEventTargetType {
         ScrollEventDocumentTarget,
         ScrollEventElementTarget
     };
 
-    static PassRefPtr<EventQueue> create(ScriptExecutionContext*);
+    static PassOwnPtr<EventQueue> create(ScriptExecutionContext*);
     ~EventQueue();
 
     void enqueueEvent(PassRefPtr<Event>);
@@ -58,14 +55,14 @@
 private:
     explicit EventQueue(ScriptExecutionContext*);
 
-    void pendingEventTimerFired();
-    void dispatchEvent(PassRefPtr<Event>);
+    void removeEvent(Event*);
 
-    OwnPtr<EventQueueTimer> m_pendingEventTimer;
-    ListHashSet<RefPtr<Event> > m_queuedEvents;
     HashSet<Node*> m_nodesWithQueuedScrollEvents;
-    
-    friend class EventQueueTimer;    
+    ScriptExecutionContext* m_scriptExecutionContext;
+
+    class EventDispatcherTask;
+    typedef HashMap<RefPtr<Event>, EventDispatcherTask*> EventTaskMap;
+    EventTaskMap m_eventTaskMap;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to