/work/obj-fuzz/dist/include/mozilla/StateWatching.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #if !defined(StateWatching_h_) |
8 | | #define StateWatching_h_ |
9 | | |
10 | | #include "mozilla/AbstractThread.h" |
11 | | #include "mozilla/Logging.h" |
12 | | #include "mozilla/TaskDispatcher.h" |
13 | | #include "mozilla/UniquePtr.h" |
14 | | #include "mozilla/Unused.h" |
15 | | |
16 | | #include "nsISupportsImpl.h" |
17 | | |
18 | | /* |
19 | | * The state-watching machinery automates the process of responding to changes |
20 | | * in various pieces of state. |
21 | | * |
22 | | * A standard programming pattern is as follows: |
23 | | * |
24 | | * mFoo = ...; |
25 | | * NotifyStuffChanged(); |
26 | | * ... |
27 | | * mBar = ...; |
28 | | * NotifyStuffChanged(); |
29 | | * |
30 | | * This pattern is error-prone and difficult to audit because it requires the |
31 | | * programmer to manually trigger the update routine. This can be especially |
32 | | * problematic when the update routine depends on numerous pieces of state, and |
33 | | * when that state is modified across a variety of helper methods. In these |
34 | | * cases the responsibility for invoking the routine is often unclear, causing |
35 | | * developers to scatter calls to it like pixie dust. This can result in |
36 | | * duplicate invocations (which is wasteful) and missing invocations in corner- |
37 | | * cases (which is a source of bugs). |
38 | | * |
39 | | * This file provides a set of primitives that automatically handle updates and |
40 | | * allow the programmers to explicitly construct a graph of state dependencies. |
41 | | * When used correctly, it eliminates the guess-work and wasted cycles described |
42 | | * above. |
43 | | * |
44 | | * There are two basic pieces: |
45 | | * (1) Objects that can be watched for updates. These inherit WatchTarget. |
46 | | * (2) Objects that receive objects and trigger processing. These inherit |
47 | | * AbstractWatcher. In the current machinery, these exist only internally |
48 | | * within the WatchManager, though that could change. |
49 | | * |
50 | | * Note that none of this machinery is thread-safe - it must all happen on the |
51 | | * same owning thread. To solve multi-threaded use-cases, use state mirroring |
52 | | * and watch the mirrored value. |
53 | | * |
54 | | * Given that semantics may change and comments tend to go out of date, we |
55 | | * deliberately don't provide usage examples here. Grep around to find them. |
56 | | */ |
57 | | |
58 | | namespace mozilla { |
59 | | |
60 | | extern LazyLogModule gStateWatchingLog; |
61 | | |
62 | | #define WATCH_LOG(x, ...) \ |
63 | 0 | MOZ_LOG(gStateWatchingLog, LogLevel::Debug, (x, ##__VA_ARGS__)) |
64 | | |
65 | | /* |
66 | | * AbstractWatcher is a superclass from which all watchers must inherit. |
67 | | */ |
68 | | class AbstractWatcher |
69 | | { |
70 | | public: |
71 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractWatcher) |
72 | 0 | AbstractWatcher() : mDestroyed(false) {} |
73 | 0 | bool IsDestroyed() { return mDestroyed; } |
74 | | virtual void Notify() = 0; |
75 | | |
76 | | protected: |
77 | 0 | virtual ~AbstractWatcher() { MOZ_ASSERT(mDestroyed); } |
78 | | bool mDestroyed; |
79 | | }; |
80 | | |
81 | | /* |
82 | | * WatchTarget is a superclass from which all watchable things must inherit. |
83 | | * Unlike AbstractWatcher, it is a fully-implemented Mix-in, and the subclass |
84 | | * needs only to invoke NotifyWatchers when something changes. |
85 | | * |
86 | | * The functionality that this class provides is not threadsafe, and should only |
87 | | * be used on the thread that owns that WatchTarget. |
88 | | */ |
89 | | class WatchTarget |
90 | | { |
91 | | public: |
92 | 0 | explicit WatchTarget(const char* aName) : mName(aName) {} |
93 | | |
94 | | void AddWatcher(AbstractWatcher* aWatcher) |
95 | 0 | { |
96 | 0 | MOZ_ASSERT(!mWatchers.Contains(aWatcher)); |
97 | 0 | mWatchers.AppendElement(aWatcher); |
98 | 0 | } |
99 | | |
100 | | void RemoveWatcher(AbstractWatcher* aWatcher) |
101 | 0 | { |
102 | 0 | MOZ_ASSERT(mWatchers.Contains(aWatcher)); |
103 | 0 | mWatchers.RemoveElement(aWatcher); |
104 | 0 | } |
105 | | |
106 | | protected: |
107 | | void NotifyWatchers() |
108 | 0 | { |
109 | 0 | WATCH_LOG("%s[%p] notifying watchers\n", mName, this); |
110 | 0 | PruneWatchers(); |
111 | 0 | for (size_t i = 0; i < mWatchers.Length(); ++i) { |
112 | 0 | mWatchers[i]->Notify(); |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | | private: |
117 | | // We don't have Watchers explicitly unregister themselves when they die, |
118 | | // because then they'd need back-references to all the WatchTargets they're |
119 | | // subscribed to, and WatchTargets aren't reference-counted. So instead we |
120 | | // just prune dead ones at appropriate times, which works just fine. |
121 | | void PruneWatchers() |
122 | 0 | { |
123 | 0 | for (int i = mWatchers.Length() - 1; i >= 0; --i) { |
124 | 0 | if (mWatchers[i]->IsDestroyed()) { |
125 | 0 | mWatchers.RemoveElementAt(i); |
126 | 0 | } |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | | nsTArray<RefPtr<AbstractWatcher>> mWatchers; |
131 | | |
132 | | protected: |
133 | | const char* mName; |
134 | | }; |
135 | | |
136 | | /* |
137 | | * Watchable is a wrapper class that turns any primitive into a WatchTarget. |
138 | | */ |
139 | | template<typename T> |
140 | | class Watchable : public WatchTarget |
141 | | { |
142 | | public: |
143 | | Watchable(const T& aInitialValue, const char* aName) |
144 | 0 | : WatchTarget(aName), mValue(aInitialValue) {} Unexecuted instantiation: mozilla::Watchable<bool>::Watchable(bool const&, char const*) Unexecuted instantiation: mozilla::Watchable<OMX_STATETYPE>::Watchable(OMX_STATETYPE const&, char const*) Unexecuted instantiation: mozilla::Watchable<int>::Watchable(int const&, char const*) |
145 | | |
146 | 0 | const T& Ref() const { return mValue; } Unexecuted instantiation: mozilla::Watchable<bool>::Ref() const Unexecuted instantiation: mozilla::Watchable<OMX_STATETYPE>::Ref() const Unexecuted instantiation: mozilla::Watchable<int>::Ref() const |
147 | 0 | operator const T&() const { return Ref(); } Unexecuted instantiation: mozilla::Watchable<bool>::operator bool const&() const Unexecuted instantiation: mozilla::Watchable<OMX_STATETYPE>::operator OMX_STATETYPE const&() const Unexecuted instantiation: mozilla::Watchable<int>::operator int const&() const |
148 | | Watchable& operator=(const T& aNewValue) |
149 | 0 | { |
150 | 0 | if (aNewValue != mValue) { |
151 | 0 | mValue = aNewValue; |
152 | 0 | NotifyWatchers(); |
153 | 0 | } |
154 | 0 |
|
155 | 0 | return *this; |
156 | 0 | } Unexecuted instantiation: mozilla::Watchable<bool>::operator=(bool const&) Unexecuted instantiation: mozilla::Watchable<OMX_STATETYPE>::operator=(OMX_STATETYPE const&) Unexecuted instantiation: mozilla::Watchable<int>::operator=(int const&) |
157 | | |
158 | | private: |
159 | | Watchable(const Watchable& aOther); // Not implemented |
160 | | Watchable& operator=(const Watchable& aOther); // Not implemented |
161 | | |
162 | | T mValue; |
163 | | }; |
164 | | |
165 | | // Manager class for state-watching. Declare one of these in any class for which |
166 | | // you want to invoke method callbacks. |
167 | | // |
168 | | // Internally, WatchManager maintains one AbstractWatcher per callback method. |
169 | | // Consumers invoke Watch/Unwatch on a particular (WatchTarget, Callback) tuple. |
170 | | // This causes an AbstractWatcher for |Callback| to be instantiated if it doesn't |
171 | | // already exist, and registers it with |WatchTarget|. |
172 | | // |
173 | | // Using Direct Tasks on the TailDispatcher, WatchManager ensures that we fire |
174 | | // watch callbacks no more than once per task, once all other operations for that |
175 | | // task have been completed. |
176 | | // |
177 | | // WatchManager<OwnerType> is intended to be declared as a member of |OwnerType| |
178 | | // objects. Given that, it and its owned objects can't hold permanent strong refs to |
179 | | // the owner, since that would keep the owner alive indefinitely. Instead, it |
180 | | // _only_ holds strong refs while waiting for Direct Tasks to fire. This ensures |
181 | | // that everything is kept alive just long enough. |
182 | | template <typename OwnerType> |
183 | | class WatchManager |
184 | | { |
185 | | public: |
186 | | typedef void(OwnerType::*CallbackMethod)(); |
187 | | explicit WatchManager(OwnerType* aOwner, AbstractThread* aOwnerThread) |
188 | 0 | : mOwner(aOwner), mOwnerThread(aOwnerThread) {} Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::WatchManager(mozilla::dom::HTMLMediaElement*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::WatchManager(mozilla::MediaDecoder*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::WatchManager(mozilla::MediaDecoderStateMachine*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::WatchManager(mozilla::ReaderProxy*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::WatchManager(mozilla::dom::TextTrackCue*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::WatchManager(mozilla::OmxDataDecoder*, mozilla::AbstractThread*) Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::WatchManager(TestStateWatching::Foo*, mozilla::AbstractThread*) |
189 | | |
190 | | ~WatchManager() |
191 | 0 | { |
192 | 0 | if (!IsShutdown()) { |
193 | 0 | Shutdown(); |
194 | 0 | } |
195 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::~WatchManager() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::~WatchManager() |
196 | | |
197 | 0 | bool IsShutdown() const { return !mOwner; } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::IsShutdown() const Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::IsShutdown() const |
198 | | |
199 | | // Shutdown needs to happen on mOwnerThread. If the WatchManager will be |
200 | | // destroyed on a different thread, Shutdown() must be called manually. |
201 | | void Shutdown() |
202 | 0 | { |
203 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
204 | 0 | for (size_t i = 0; i < mWatchers.Length(); ++i) { |
205 | 0 | mWatchers[i]->Destroy(); |
206 | 0 | } |
207 | 0 | mWatchers.Clear(); |
208 | 0 | mOwner = nullptr; |
209 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::Shutdown() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::Shutdown() |
210 | | |
211 | | void Watch(WatchTarget& aTarget, CallbackMethod aMethod) |
212 | 0 | { |
213 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
214 | 0 | aTarget.AddWatcher(&EnsureWatcher(aMethod)); |
215 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::Watch(mozilla::WatchTarget&, void (mozilla::dom::TextTrackCue::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::Watch(mozilla::WatchTarget&, void (mozilla::dom::HTMLMediaElement::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::Watch(mozilla::WatchTarget&, void (mozilla::MediaDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::Watch(mozilla::WatchTarget&, void (mozilla::MediaDecoderStateMachine::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::Watch(mozilla::WatchTarget&, void (mozilla::ReaderProxy::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::Watch(mozilla::WatchTarget&, void (mozilla::OmxDataDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::Watch(mozilla::WatchTarget&, void (TestStateWatching::Foo::*)()) |
216 | | |
217 | | void Unwatch(WatchTarget& aTarget, CallbackMethod aMethod) |
218 | 0 | { |
219 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
220 | 0 | PerCallbackWatcher* watcher = GetWatcher(aMethod); |
221 | 0 | MOZ_ASSERT(watcher); |
222 | 0 | aTarget.RemoveWatcher(watcher); |
223 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::Unwatch(mozilla::WatchTarget&, void (mozilla::dom::TextTrackCue::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::Unwatch(mozilla::WatchTarget&, void (mozilla::OmxDataDecoder::*)()) |
224 | | |
225 | | void ManualNotify(CallbackMethod aMethod) |
226 | | { |
227 | | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
228 | | PerCallbackWatcher* watcher = GetWatcher(aMethod); |
229 | | MOZ_ASSERT(watcher); |
230 | | watcher->Notify(); |
231 | | } |
232 | | |
233 | | private: |
234 | | class PerCallbackWatcher : public AbstractWatcher |
235 | | { |
236 | | public: |
237 | | PerCallbackWatcher(OwnerType* aOwner, AbstractThread* aOwnerThread, CallbackMethod aMethod) |
238 | 0 | : mOwner(aOwner), mOwnerThread(aOwnerThread), mCallbackMethod(aMethod) {} Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::PerCallbackWatcher(mozilla::dom::HTMLMediaElement*, mozilla::AbstractThread*, void (mozilla::dom::HTMLMediaElement::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::PerCallbackWatcher(mozilla::MediaDecoder*, mozilla::AbstractThread*, void (mozilla::MediaDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::PerCallbackWatcher(mozilla::MediaDecoderStateMachine*, mozilla::AbstractThread*, void (mozilla::MediaDecoderStateMachine::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::PerCallbackWatcher(mozilla::dom::TextTrackCue*, mozilla::AbstractThread*, void (mozilla::dom::TextTrackCue::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::PerCallbackWatcher(mozilla::ReaderProxy*, mozilla::AbstractThread*, void (mozilla::ReaderProxy::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::PerCallbackWatcher(mozilla::OmxDataDecoder*, mozilla::AbstractThread*, void (mozilla::OmxDataDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::PerCallbackWatcher(TestStateWatching::Foo*, mozilla::AbstractThread*, void (TestStateWatching::Foo::*)()) |
239 | | |
240 | | void Destroy() |
241 | 0 | { |
242 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
243 | 0 | mDestroyed = true; |
244 | 0 | mOwner = nullptr; |
245 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::Destroy() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::Destroy() |
246 | | |
247 | | void Notify() override |
248 | 0 | { |
249 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
250 | 0 | MOZ_DIAGNOSTIC_ASSERT(mOwner, "mOwner is only null after destruction, " |
251 | 0 | "at which point we shouldn't be notified"); |
252 | 0 | if (mStrongRef) { |
253 | 0 | // We've already got a notification job in the pipe. |
254 | 0 | return; |
255 | 0 | } |
256 | 0 | mStrongRef = mOwner; // Hold the owner alive while notifying. |
257 | 0 |
|
258 | 0 | // Queue up our notification jobs to run in a stable state. |
259 | 0 | mOwnerThread->TailDispatcher().AddDirectTask( |
260 | 0 | NewRunnableMethod("WatchManager::PerCallbackWatcher::DoNotify", |
261 | 0 | this, |
262 | 0 | &PerCallbackWatcher::DoNotify)); |
263 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::Notify() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::Notify() |
264 | | |
265 | | bool CallbackMethodIs(CallbackMethod aMethod) const |
266 | 0 | { |
267 | 0 | return mCallbackMethod == aMethod; |
268 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::dom::TextTrackCue::*)()) const Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::dom::HTMLMediaElement::*)()) const Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::MediaDecoder::*)()) const Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::MediaDecoderStateMachine::*)()) const Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::ReaderProxy::*)()) const Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::CallbackMethodIs(void (mozilla::OmxDataDecoder::*)()) const Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::CallbackMethodIs(void (TestStateWatching::Foo::*)()) const |
269 | | |
270 | | private: |
271 | 0 | ~PerCallbackWatcher() {} Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::~PerCallbackWatcher() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::~PerCallbackWatcher() |
272 | | |
273 | | void DoNotify() |
274 | 0 | { |
275 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
276 | 0 | MOZ_ASSERT(mStrongRef); |
277 | 0 | RefPtr<OwnerType> ref = mStrongRef.forget(); |
278 | 0 | if (!mDestroyed) { |
279 | 0 | ((*ref).*mCallbackMethod)(); |
280 | 0 | } |
281 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::PerCallbackWatcher::DoNotify() Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::PerCallbackWatcher::DoNotify() |
282 | | |
283 | | OwnerType* mOwner; // Never null. |
284 | | RefPtr<OwnerType> mStrongRef; // Only non-null when notifying. |
285 | | RefPtr<AbstractThread> mOwnerThread; |
286 | | CallbackMethod mCallbackMethod; |
287 | | }; |
288 | | |
289 | | PerCallbackWatcher* GetWatcher(CallbackMethod aMethod) |
290 | 0 | { |
291 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
292 | 0 | for (size_t i = 0; i < mWatchers.Length(); ++i) { |
293 | 0 | if (mWatchers[i]->CallbackMethodIs(aMethod)) { |
294 | 0 | return mWatchers[i]; |
295 | 0 | } |
296 | 0 | } |
297 | 0 | return nullptr; |
298 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::GetWatcher(void (mozilla::dom::TextTrackCue::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::GetWatcher(void (mozilla::dom::HTMLMediaElement::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::GetWatcher(void (mozilla::MediaDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::GetWatcher(void (mozilla::MediaDecoderStateMachine::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::GetWatcher(void (mozilla::ReaderProxy::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::GetWatcher(void (mozilla::OmxDataDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::GetWatcher(void (TestStateWatching::Foo::*)()) |
299 | | |
300 | | PerCallbackWatcher& EnsureWatcher(CallbackMethod aMethod) |
301 | 0 | { |
302 | 0 | MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); |
303 | 0 | PerCallbackWatcher* watcher = GetWatcher(aMethod); |
304 | 0 | if (watcher) { |
305 | 0 | return *watcher; |
306 | 0 | } |
307 | 0 | watcher = mWatchers.AppendElement(new PerCallbackWatcher(mOwner, mOwnerThread, aMethod))->get(); |
308 | 0 | return *watcher; |
309 | 0 | } Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::TextTrackCue>::EnsureWatcher(void (mozilla::dom::TextTrackCue::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::dom::HTMLMediaElement>::EnsureWatcher(void (mozilla::dom::HTMLMediaElement::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoder>::EnsureWatcher(void (mozilla::MediaDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::MediaDecoderStateMachine>::EnsureWatcher(void (mozilla::MediaDecoderStateMachine::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::ReaderProxy>::EnsureWatcher(void (mozilla::ReaderProxy::*)()) Unexecuted instantiation: mozilla::WatchManager<mozilla::OmxDataDecoder>::EnsureWatcher(void (mozilla::OmxDataDecoder::*)()) Unexecuted instantiation: mozilla::WatchManager<TestStateWatching::Foo>::EnsureWatcher(void (TestStateWatching::Foo::*)()) |
310 | | |
311 | | nsTArray<RefPtr<PerCallbackWatcher>> mWatchers; |
312 | | OwnerType* mOwner; |
313 | | RefPtr<AbstractThread> mOwnerThread; |
314 | | }; |
315 | | |
316 | | #undef WATCH_LOG |
317 | | |
318 | | } // namespace mozilla |
319 | | |
320 | | #endif |