OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * Copyright (C) 2013 Google Inc. All Rights Reserved. | 3 * Copyright (C) 2013 Google Inc. All Rights Reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 20 matching lines...) Expand all Loading... |
31 #include "wtf/HashSet.h" | 31 #include "wtf/HashSet.h" |
32 #include "wtf/TemporaryChange.h" | 32 #include "wtf/TemporaryChange.h" |
33 | 33 |
34 namespace blink { | 34 namespace blink { |
35 | 35 |
36 template<typename T, typename Observer> | 36 template<typename T, typename Observer> |
37 class LifecycleNotifier { | 37 class LifecycleNotifier { |
38 public: | 38 public: |
39 virtual ~LifecycleNotifier(); | 39 virtual ~LifecycleNotifier(); |
40 | 40 |
41 void addObserver(Observer*); | 41 void addObserver(Observer*, bool); |
42 void removeObserver(Observer*); | 42 void removeObserver(Observer*, bool); |
43 | 43 |
44 // notifyContextDestroyed() should be explicitly dispatched from an | 44 // notifyContextDestroyed() should be explicitly dispatched from an |
45 // observed context to notify observers that contextDestroyed(). | 45 // observed context to notify observers that contextDestroyed(). |
46 // | 46 // |
47 // When contextDestroyed() is called, the observer's lifecycleContext() | 47 // When contextDestroyed() is called, the observer's lifecycleContext() |
48 // is still valid and safe to use during the notification. | 48 // is still valid and safe to use during the notification. |
49 virtual void notifyContextDestroyed(); | 49 virtual void notifyContextDestroyed(); |
50 | 50 |
51 DEFINE_INLINE_VIRTUAL_TRACE() | 51 DEFINE_INLINE_VIRTUAL_TRACE() |
52 { | 52 { |
(...skipping 20 matching lines...) Expand all Loading... |
73 | 73 |
74 protected: | 74 protected: |
75 using ObserverSet = WillBeHeapHashSet<RawPtrWillBeWeakMember<Observer>>; | 75 using ObserverSet = WillBeHeapHashSet<RawPtrWillBeWeakMember<Observer>>; |
76 | 76 |
77 // FIXME: Oilpan: make LifecycleNotifier<> a GC mixin, somehow. ExecutionCon
text | 77 // FIXME: Oilpan: make LifecycleNotifier<> a GC mixin, somehow. ExecutionCon
text |
78 // is the problematic case, as it would then be a class with two GC mixin | 78 // is the problematic case, as it would then be a class with two GC mixin |
79 // bases, but cannot itself derive from a GC base class also. | 79 // bases, but cannot itself derive from a GC base class also. |
80 GC_PLUGIN_IGNORE("467502") | 80 GC_PLUGIN_IGNORE("467502") |
81 ObserverSet m_observers; | 81 ObserverSet m_observers; |
82 | 82 |
| 83 #if !ENABLE(OILPAN) |
| 84 bool isObserverAlive(Observer*&) const; |
| 85 #endif |
| 86 |
83 #if ENABLE(ASSERT) | 87 #if ENABLE(ASSERT) |
84 T* context() { return static_cast<T*>(this); } | 88 T* context() { return static_cast<T*>(this); } |
85 #endif | 89 #endif |
86 | 90 |
87 private: | 91 private: |
88 bool m_didCallContextDestroyed; | 92 bool m_didCallContextDestroyed; |
89 }; | 93 }; |
90 | 94 |
| 95 #if !ENABLE(OILPAN) |
| 96 template<typename T, typename Observer> |
| 97 bool LifecycleNotifier<T, Observer>::isObserverAlive(Observer*& observer) const |
| 98 { |
| 99 if (reinterpret_cast<uintptr_t>(observer) & 0x1) { |
| 100 observer = reinterpret_cast<Observer*>(reinterpret_cast<uintptr_t>(obser
ver) & ~0x1); |
| 101 if (Heap::willObjectBeLazilySwept(observer)) |
| 102 return false; |
| 103 } |
| 104 return true; |
| 105 } |
| 106 #endif |
| 107 |
91 template<typename T, typename Observer> | 108 template<typename T, typename Observer> |
92 inline LifecycleNotifier<T, Observer>::~LifecycleNotifier() | 109 inline LifecycleNotifier<T, Observer>::~LifecycleNotifier() |
93 { | 110 { |
94 // FIXME: Enable the following ASSERT. Also see a FIXME in Document::detach(
). | 111 // FIXME: Enable the following ASSERT. Also see a FIXME in Document::detach(
). |
95 // ASSERT(!m_observers.size() || m_didCallContextDestroyed); | 112 // ASSERT(!m_observers.size() || m_didCallContextDestroyed); |
96 | 113 |
97 #if !ENABLE(OILPAN) | 114 #if !ENABLE(OILPAN) |
98 TemporaryChange<IterationType> scope(m_iterating, IteratingOverAll); | 115 TemporaryChange<IterationType> scope(m_iterating, IteratingOverAll); |
99 for (Observer* observer : m_observers) { | 116 for (Observer* observer : m_observers) { |
| 117 if (!isObserverAlive(observer)) |
| 118 continue; |
100 ASSERT(observer->lifecycleContext() == context()); | 119 ASSERT(observer->lifecycleContext() == context()); |
101 observer->clearLifecycleContext(); | 120 observer->clearLifecycleContext(); |
102 } | 121 } |
103 #endif | 122 #endif |
104 } | 123 } |
105 | 124 |
106 template<typename T, typename Observer> | 125 template<typename T, typename Observer> |
107 inline void LifecycleNotifier<T, Observer>::notifyContextDestroyed() | 126 inline void LifecycleNotifier<T, Observer>::notifyContextDestroyed() |
108 { | 127 { |
109 // Don't notify contextDestroyed() twice. | 128 // Don't notify contextDestroyed() twice. |
110 if (m_didCallContextDestroyed) | 129 if (m_didCallContextDestroyed) |
111 return; | 130 return; |
112 | 131 |
113 TemporaryChange<IterationType> scope(m_iterating, IteratingOverAll); | 132 TemporaryChange<IterationType> scope(m_iterating, IteratingOverAll); |
114 Vector<Observer*> snapshotOfObservers; | 133 Vector<Observer*> snapshotOfObservers; |
115 copyToVector(m_observers, snapshotOfObservers); | 134 copyToVector(m_observers, snapshotOfObservers); |
116 for (Observer* observer : snapshotOfObservers) { | 135 for (Observer* observer : snapshotOfObservers) { |
| 136 #if !ENABLE(OILPAN) |
| 137 if (!isObserverAlive(observer)) |
| 138 continue; |
| 139 #endif |
117 // FIXME: Oilpan: At the moment, it's possible that the Observer is | 140 // FIXME: Oilpan: At the moment, it's possible that the Observer is |
118 // destructed during the iteration. Once we enable Oilpan by default | 141 // destructed during the iteration. Once we enable Oilpan by default |
119 // for Observers, we can remove the hack by making m_observers | 142 // for Observers, we can remove the hack by making m_observers |
120 // a HeapHashSet<WeakMember<Observers>>. (i.e., we can just iterate | 143 // a HeapHashSet<WeakMember<Observers>>. (i.e., we can just iterate |
121 // m_observers without taking a snapshot). | 144 // m_observers without taking a snapshot). |
122 if (m_observers.contains(observer)) { | 145 if (m_observers.contains(observer)) { |
123 ASSERT(observer->lifecycleContext() == context()); | 146 ASSERT(observer->lifecycleContext() == context()); |
124 observer->contextDestroyed(); | 147 observer->contextDestroyed(); |
125 } | 148 } |
126 } | 149 } |
127 m_didCallContextDestroyed = true; | 150 m_didCallContextDestroyed = true; |
128 } | 151 } |
129 | 152 |
130 template<typename T, typename Observer> | 153 template<typename T, typename Observer> |
131 inline void LifecycleNotifier<T, Observer>::addObserver(Observer* observer) | 154 inline void LifecycleNotifier<T, Observer>::addObserver(Observer* observer, bool
isGarbageCollected) |
132 { | 155 { |
133 RELEASE_ASSERT(m_iterating != IteratingOverAll); | 156 RELEASE_ASSERT(m_iterating != IteratingOverAll); |
| 157 #if !ENABLE(OILPAN) |
| 158 if (isGarbageCollected) |
| 159 observer = reinterpret_cast<Observer*>(reinterpret_cast<uintptr_t>(obser
ver) | 1); |
| 160 #else |
| 161 (void)isGarbageCollected; |
| 162 #endif |
134 m_observers.add(observer); | 163 m_observers.add(observer); |
135 } | 164 } |
136 | 165 |
137 template<typename T, typename Observer> | 166 template<typename T, typename Observer> |
138 inline void LifecycleNotifier<T, Observer>::removeObserver(Observer* observer) | 167 inline void LifecycleNotifier<T, Observer>::removeObserver(Observer* observer, b
ool isGarbageCollected) |
139 { | 168 { |
| 169 #if !ENABLE(OILPAN) |
| 170 if (isGarbageCollected) |
| 171 observer = reinterpret_cast<Observer*>(reinterpret_cast<uintptr_t>(obser
ver) | 1); |
| 172 #else |
| 173 (void)isGarbageCollected; |
| 174 #endif |
140 m_observers.remove(observer); | 175 m_observers.remove(observer); |
141 } | 176 } |
142 | 177 |
143 } // namespace blink | 178 } // namespace blink |
144 | 179 |
145 #endif // LifecycleNotifier_h | 180 #endif // LifecycleNotifier_h |
OLD | NEW |