Coverage Report

Created: 2018-09-25 14:53

/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