Index: third_party/WebKit/Source/platform/LifecycleNotifier.h |
diff --git a/third_party/WebKit/Source/platform/LifecycleNotifier.h b/third_party/WebKit/Source/platform/LifecycleNotifier.h |
index 2f2b0609bc7e18f922f5ad642a8f6b712a694686..72d6680d78628c5f095463ca3978c2cf48b343ca 100644 |
--- a/third_party/WebKit/Source/platform/LifecycleNotifier.h |
+++ b/third_party/WebKit/Source/platform/LifecycleNotifier.h |
@@ -67,11 +67,14 @@ protected: |
using ObserverSet = HeapHashSet<WeakMember<Observer>>; |
+ void removePending(ObserverSet&); |
+ |
enum IterationState { |
- AllowingNone = 0, |
- AllowingAddition, |
- AllowingRemoval, |
- NotIterating = AllowingAddition | AllowingRemoval, |
+ AllowingNone = 0, |
+ AllowingAddition = 1, |
+ AllowingRemoval = 2, |
+ NotIterating = AllowingAddition | AllowingRemoval, |
+ AllowPendingRemoval = 4, |
}; |
// Iteration state is recorded while iterating the observer set, |
@@ -110,10 +113,28 @@ inline void LifecycleNotifier<T, Observer>::addObserver(Observer* observer) |
template<typename T, typename Observer> |
inline void LifecycleNotifier<T, Observer>::removeObserver(Observer* observer) |
{ |
+ // If immediate removal isn't currently allowed, |
+ // |observer| is recorded for pending removal. |
+ if (m_iterationState & AllowPendingRemoval) { |
+ m_observers.add(observer); |
+ return; |
+ } |
RELEASE_ASSERT(m_iterationState & AllowingRemoval); |
m_observers.remove(observer); |
} |
+template<typename T, typename Observer> |
+inline void LifecycleNotifier<T, Observer>::removePending(ObserverSet& observers) |
+{ |
+ if (m_observers.size()) { |
+ // Prevent allocation (==shrinking) while removing; |
+ // the table is likely to become garbage soon. |
+ ThreadState::NoAllocationScope scope(ThreadState::current()); |
+ observers.removeAll(m_observers); |
+ } |
+ m_observers.swap(observers); |
+} |
+ |
} // namespace blink |
#endif // LifecycleNotifier_h |