mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1160064 - Give WatchManager an owner thread and make sure everything happens there. r=jww
This commit is contained in:
parent
a6a1df6eb5
commit
75cd0709f1
@ -2042,7 +2042,7 @@ HTMLMediaElement::LookupMediaElementURITable(nsIURI* aURI)
|
||||
|
||||
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo),
|
||||
mWatchManager(this),
|
||||
mWatchManager(this, AbstractThread::MainThread()),
|
||||
mCurrentLoadID(0),
|
||||
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
|
||||
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING, "HTMLMediaElement::mReadyState"),
|
||||
|
@ -595,7 +595,7 @@ bool MediaDecoder::IsInfinite()
|
||||
}
|
||||
|
||||
MediaDecoder::MediaDecoder() :
|
||||
mWatchManager(this),
|
||||
mWatchManager(this, AbstractThread::MainThread()),
|
||||
mNextFrameStatus(AbstractThread::MainThread(),
|
||||
MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
|
||||
"MediaDecoder::mNextFrameStatus (Mirror)"),
|
||||
|
@ -203,7 +203,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
bool aRealTime) :
|
||||
mDecoder(aDecoder),
|
||||
mTaskQueue(new MediaTaskQueue(GetMediaThreadPool(), /* aAssertTailDispatch = */ true)),
|
||||
mWatchManager(this),
|
||||
mWatchManager(this, mTaskQueue),
|
||||
mRealTime(aRealTime),
|
||||
mDispatchedStateMachine(false),
|
||||
mDelayedScheduler(this),
|
||||
@ -2529,6 +2529,9 @@ MediaDecoderStateMachine::FinishShutdown()
|
||||
mNextPlayState.DisconnectIfConnected();
|
||||
mNextFrameStatus.DisconnectAll();
|
||||
|
||||
// Shut down the watch manager before shutting down our task queue.
|
||||
mWatchManager.Shutdown();
|
||||
|
||||
MOZ_ASSERT(mState == DECODER_STATE_SHUTDOWN,
|
||||
"How did we escape from the shutdown state?");
|
||||
// We must daisy-chain these events to destroy the decoder. We must
|
||||
|
@ -183,23 +183,39 @@ class WatchManager
|
||||
{
|
||||
public:
|
||||
typedef void(OwnerType::*CallbackMethod)();
|
||||
explicit WatchManager(OwnerType* aOwner)
|
||||
: mOwner(aOwner) {}
|
||||
explicit WatchManager(OwnerType* aOwner, AbstractThread* aOwnerThread)
|
||||
: mOwner(aOwner), mOwnerThread(aOwnerThread) {}
|
||||
|
||||
~WatchManager()
|
||||
{
|
||||
if (!IsShutdown()) {
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsShutdown() const { return !mOwner; }
|
||||
|
||||
// Shutdown needs to happen on mOwnerThread. If the WatchManager will be
|
||||
// destroyed on a different thread, Shutdown() must be called manually.
|
||||
void Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
for (size_t i = 0; i < mWatchers.Length(); ++i) {
|
||||
mWatchers[i]->Destroy();
|
||||
}
|
||||
mWatchers.Clear();
|
||||
mOwner = nullptr;
|
||||
}
|
||||
|
||||
void Watch(WatchTarget& aTarget, CallbackMethod aMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
aTarget.AddWatcher(&EnsureWatcher(aMethod));
|
||||
}
|
||||
|
||||
void Unwatch(WatchTarget& aTarget, CallbackMethod aMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
PerCallbackWatcher* watcher = GetWatcher(aMethod);
|
||||
MOZ_ASSERT(watcher);
|
||||
aTarget.RemoveWatcher(watcher);
|
||||
@ -207,6 +223,7 @@ public:
|
||||
|
||||
void ManualNotify(CallbackMethod aMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
PerCallbackWatcher* watcher = GetWatcher(aMethod);
|
||||
MOZ_ASSERT(watcher);
|
||||
watcher->Notify();
|
||||
@ -216,17 +233,19 @@ private:
|
||||
class PerCallbackWatcher : public AbstractWatcher
|
||||
{
|
||||
public:
|
||||
PerCallbackWatcher(OwnerType* aOwner, CallbackMethod aMethod)
|
||||
: mOwner(aOwner), mCallbackMethod(aMethod) {}
|
||||
PerCallbackWatcher(OwnerType* aOwner, AbstractThread* aOwnerThread, CallbackMethod aMethod)
|
||||
: mOwner(aOwner), mOwnerThread(aOwnerThread), mCallbackMethod(aMethod) {}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
mDestroyed = true;
|
||||
mOwner = nullptr;
|
||||
}
|
||||
|
||||
void Notify() override
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOwner, "mOwner is only null after destruction, "
|
||||
"at which point we shouldn't be notified");
|
||||
if (mStrongRef) {
|
||||
@ -237,7 +256,7 @@ private:
|
||||
|
||||
// Queue up our notification jobs to run in a stable state.
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &PerCallbackWatcher::DoNotify);
|
||||
AbstractThread::GetCurrent()->TailDispatcher().AddDirectTask(r.forget());
|
||||
mOwnerThread->TailDispatcher().AddDirectTask(r.forget());
|
||||
}
|
||||
|
||||
bool CallbackMethodIs(CallbackMethod aMethod) const
|
||||
@ -250,6 +269,7 @@ private:
|
||||
|
||||
void DoNotify()
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
MOZ_ASSERT(mStrongRef);
|
||||
nsRefPtr<OwnerType> ref = mStrongRef.forget();
|
||||
((*ref).*mCallbackMethod)();
|
||||
@ -257,11 +277,13 @@ private:
|
||||
|
||||
OwnerType* mOwner; // Never null.
|
||||
nsRefPtr<OwnerType> mStrongRef; // Only non-null when notifying.
|
||||
nsRefPtr<AbstractThread> mOwnerThread;
|
||||
CallbackMethod mCallbackMethod;
|
||||
};
|
||||
|
||||
PerCallbackWatcher* GetWatcher(CallbackMethod aMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
for (size_t i = 0; i < mWatchers.Length(); ++i) {
|
||||
if (mWatchers[i]->CallbackMethodIs(aMethod)) {
|
||||
return mWatchers[i];
|
||||
@ -272,16 +294,18 @@ private:
|
||||
|
||||
PerCallbackWatcher& EnsureWatcher(CallbackMethod aMethod)
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
PerCallbackWatcher* watcher = GetWatcher(aMethod);
|
||||
if (watcher) {
|
||||
return *watcher;
|
||||
}
|
||||
watcher = mWatchers.AppendElement(new PerCallbackWatcher(mOwner, aMethod))->get();
|
||||
watcher = mWatchers.AppendElement(new PerCallbackWatcher(mOwner, mOwnerThread, aMethod))->get();
|
||||
return *watcher;
|
||||
}
|
||||
|
||||
nsTArray<nsRefPtr<PerCallbackWatcher>> mWatchers;
|
||||
OwnerType* mOwner;
|
||||
nsRefPtr<AbstractThread> mOwnerThread;
|
||||
};
|
||||
|
||||
#undef WATCH_LOG
|
||||
|
Loading…
Reference in New Issue
Block a user