Chromium Code Reviews| Index: Source/core/frame/PlatformEventDispatcher.cpp |
| diff --git a/Source/core/frame/PlatformEventDispatcher.cpp b/Source/core/frame/PlatformEventDispatcher.cpp |
| index b588df26190466b88d871cbc12c42ad46145b881..b7f5761c197d8ca31edd8e32fc24643c134485c2 100644 |
| --- a/Source/core/frame/PlatformEventDispatcher.cpp |
| +++ b/Source/core/frame/PlatformEventDispatcher.cpp |
| @@ -11,56 +11,27 @@ |
| namespace blink { |
| PlatformEventDispatcher::PlatformEventDispatcher() |
| - : m_needsPurge(false) |
| - , m_isDispatching(false) |
| + : m_isDispatching(false) |
| { |
| } |
| void PlatformEventDispatcher::addController(PlatformEventController* controller) |
| { |
| + ASSERT(controller); |
| + |
| bool wasEmpty = m_controllers.isEmpty(); |
| - if (!m_controllers.contains(controller)) |
| - m_controllers.append(controller); |
| + m_controllers.add(controller); |
| if (wasEmpty) |
| startListening(); |
| } |
| void PlatformEventDispatcher::removeController(PlatformEventController* controller) |
| { |
| - // Do not actually remove the controller from the vector, instead zero them out. |
| - // The zeros are removed in these two cases: |
| - // 1. either immediately if we are not dispatching any events, |
| - // 2. or after events to all controllers have dispatched (see notifyControllers()). |
| - // This is to correctly handle the re-entrancy case when a controller is destroyed |
| - // while the events are still being dispatched. |
| - size_t index = m_controllers.find(controller); |
| - if (index == kNotFound) |
| + if (!m_controllers.contains(controller)) |
| return; |
| - m_controllers[index] = nullptr; |
| - m_needsPurge = true; |
| - |
| - if (!m_isDispatching) |
| - purgeControllers(); |
| -} |
| - |
| -void PlatformEventDispatcher::purgeControllers() |
| -{ |
| - ASSERT(m_needsPurge); |
| - |
| - size_t i = 0; |
| - while (i < m_controllers.size()) { |
| - if (!m_controllers[i]) { |
| - m_controllers[i] = m_controllers.last(); |
| - m_controllers.removeLast(); |
| - } else { |
| - ++i; |
| - } |
| - } |
| - |
| - m_needsPurge = false; |
| - |
| - if (m_controllers.isEmpty()) |
| + m_controllers.remove(controller); |
| + if (!m_isDispatching && m_controllers.isEmpty()) |
| stopListening(); |
| } |
| @@ -68,38 +39,29 @@ void PlatformEventDispatcher::notifyControllers() |
| { |
| { |
| TemporaryChange<bool> changeIsDispatching(m_isDispatching, true); |
| - // Don't notify controllers removed or added during event dispatch. |
| - size_t size = m_controllers.size(); |
| - for (size_t i = 0; i < size; ++i) { |
| - if (m_controllers[i]) |
| - m_controllers[i]->didUpdateData(); |
| + // m_controllers can be restructured in addController/removeController run on other threads. |
|
timvolodine
2015/08/20 11:16:17
what other threads? I thought blink was single-thr
peria
2015/08/21 03:33:45
Oops, it comes from my misunderstanding.
Dropped t
|
| + // Thus we take a snapshot and restore into a Vector to access all elements. |
| + WillBeHeapHashSet<RawPtrWillBeWeakMember<PlatformEventController>> snapshotSet(m_controllers); |
| + HeapVector<PlatformEventController*> snapshotVector; |
| + for (PlatformEventController* controller : snapshotSet) { |
| + snapshotVector.append(controller); |
|
timvolodine
2015/08/20 11:16:17
why is it necessary to create both snapshotVector
peria
2015/08/21 03:33:45
snapshotSet was introduced to avoid accessing newl
peria
2015/08/21 03:33:45
We may remove using snapshotSet.
timvolodine
2015/08/21 15:03:32
yeah looks like it's not really needed
|
| + } |
| + for (PlatformEventController* controller : snapshotVector) { |
| + // Skip a controller which is removed during dispatching. |
| + if (m_controllers.contains(controller)) |
|
timvolodine
2015/08/20 11:16:17
also, how expensive is 'contains' here? the notify
timvolodine
2015/08/20 11:16:17
is it possible to remove and then re-add the same
peria
2015/08/21 03:33:45
I think we can, but am not sure.
peria
2015/08/21 03:33:45
Hmm, unfortunately I don't know the performance re
peria
2015/08/21 05:34:19
It must be more expensive than checking a nullptr,
timvolodine
2015/08/21 15:03:32
we cannot get rid of 'contains' because of re-entr
|
| + controller->didUpdateData(); |
| } |
| } |
| - if (m_needsPurge) |
| - purgeControllers(); |
| + if (m_controllers.isEmpty()) |
| + stopListening(); |
| } |
| DEFINE_TRACE(PlatformEventDispatcher) |
| { |
| #if ENABLE(OILPAN) |
| - // Trace the backing store, the weak(&bare) element references won't be. |
| visitor->trace(m_controllers); |
| - visitor->template registerWeakMembers<PlatformEventDispatcher, &PlatformEventDispatcher::clearWeakMembers>(this); |
| #endif |
| } |
| -#if ENABLE(OILPAN) |
| -void PlatformEventDispatcher::clearWeakMembers(Visitor* visitor) |
| -{ |
| - for (size_t i = 0; i < m_controllers.size(); ++i) { |
| - if (!Heap::isHeapObjectAlive(m_controllers[i])) { |
| - m_controllers[i] = nullptr; |
| - m_needsPurge = true; |
| - } |
| - } |
| - // Next notification will purge the empty slots. |
| -} |
| -#endif |
| - |
| } // namespace blink |