Bug 1160064 - Switch mirror/canonical initialization to happen in the constructor. r=jww

The goal here is to hoist all meaningful watcher/mirror/canonical manipulation
onto the owner thread. But since that must necessarily happen asynchronously,
we need to make sure that canonicals are in a sane state immediately upon
creation, since otherwise a mirror from another thread may attempt to connect to
a not-yet-initialized canonical.
This commit is contained in:
Bobby Holley 2015-04-30 00:21:43 -07:00
parent a927a49fdc
commit e4d299cfff
3 changed files with 29 additions and 36 deletions

View File

@ -596,6 +596,9 @@ bool MediaDecoder::IsInfinite()
MediaDecoder::MediaDecoder() :
mWatchManager(this),
mNextFrameStatus(AbstractThread::MainThread(),
MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
"MediaDecoder::mNextFrameStatus (Mirror)"),
mDecoderPosition(0),
mPlaybackPosition(0),
mCurrentTime(0.0),
@ -606,6 +609,10 @@ MediaDecoder::MediaDecoder() :
mMediaSeekable(true),
mSameOriginMedia(false),
mReentrantMonitor("media.decoder"),
mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
"MediaDecoder::mPlayState (Canonical)"),
mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED,
"MediaDecoder::mNextState (Canonical)"),
mIgnoreProgressData(false),
mInfiniteStream(false),
mOwner(nullptr),
@ -628,15 +635,6 @@ MediaDecoder::MediaDecoder() :
MOZ_ASSERT(NS_IsMainThread());
MediaMemoryTracker::AddMediaDecoder(this);
// Initialize canonicals.
mPlayState.Init(AbstractThread::MainThread(), PLAY_STATE_LOADING, "MediaDecoder::mPlayState (Canonical)");
mNextState.Init(AbstractThread::MainThread(), PLAY_STATE_PAUSED, "MediaDecoder::mNextState (Canonical)");
// Initialize mirrors.
mNextFrameStatus.Init(AbstractThread::MainThread(), MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
"MediaDecoder::mNextFrameStatus (Mirror)");
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
// Initialize watchers.

View File

@ -212,6 +212,14 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mStartTime(-1),
mEndTime(-1),
mDurationSet(false),
mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING,
"MediaDecoderStateMachine::mPlayState (Mirror)",
aDecoder->CanonicalPlayState()),
mNextPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED,
"MediaDecoderStateMachine::mNextPlayState (Mirror)",
aDecoder->CanonicalNextPlayState()),
mNextFrameStatus(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
"MediaDecoderStateMachine::mNextFrameStatus (Canonical)"),
mFragmentEndTime(-1),
mReader(aReader),
mCurrentFrameTime(0),
@ -251,16 +259,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
// Initialize canonicals.
mNextFrameStatus.Init(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
"MediaDecoderStateMachine::mNextFrameStatus (Canonical)");
// Initialize mirrors.
mPlayState.Init(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING, "MediaDecoderStateMachine::mPlayState (Mirror)",
aDecoder->CanonicalPlayState());
mNextPlayState.Init(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED, "MediaDecoderStateMachine::mNextPlayState (Mirror)",
aDecoder->CanonicalNextPlayState());
// Initialize watchers.
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);

View File

@ -112,8 +112,13 @@ template<typename T>
class Canonical
{
public:
Canonical() {}
~Canonical() { MOZ_DIAGNOSTIC_ASSERT(mImpl, "Should have initialized me"); }
Canonical(AbstractThread* aThread, const T& aInitialValue, const char* aName)
{
mImpl = new Impl(aThread, aInitialValue, aName);
}
~Canonical() {}
private:
class Impl : public AbstractCanonical<T>, public WatchTarget
@ -233,11 +238,6 @@ public:
// NB: Because mirror-initiated disconnection can race with canonical-
// initiated disconnection, a canonical should never be reinitialized.
void Init(AbstractThread* aThread, const T& aInitialValue, const char* aName)
{
mImpl = new Impl(aThread, aInitialValue, aName);
}
// Forward control operations to the Impl.
void DisconnectAll() { return mImpl->DisconnectAll(); }
@ -272,10 +272,14 @@ template<typename T>
class Mirror
{
public:
Mirror() {}
Mirror(AbstractThread* aThread, const T& aInitialValue, const char* aName,
AbstractCanonical<T>* aCanonical = nullptr)
{
mImpl = new Impl(aThread, aInitialValue, aName, aCanonical);
}
~Mirror()
{
MOZ_DIAGNOSTIC_ASSERT(mImpl, "Should have initialized me");
if (mImpl->OwnerThread()->IsCurrentThreadIn()) {
mImpl->DisconnectIfConnected();
} else {
@ -371,14 +375,6 @@ private:
};
public:
// NB: Because mirror-initiated disconnection can race with canonical-
// initiated disconnection, a mirror should never be reinitialized.
void Init(AbstractThread* aThread, const T& aInitialValue, const char* aName,
AbstractCanonical<T>* aCanonical = nullptr)
{
mImpl = new Impl(aThread, aInitialValue, aName, aCanonical);
}
// Forward control operations to the Impl<T>.
void Connect(AbstractCanonical<T>* aCanonical) { mImpl->Connect(aCanonical); }
void DisconnectIfConnected() { mImpl->DisconnectIfConnected(); }