Bug 1123983 - Implement exclusivity checking for MediaPromises. r=cpearce

This commit is contained in:
Bobby Holley 2015-01-21 14:34:26 -08:00
parent 5a43979bbc
commit a18cc7d480
3 changed files with 23 additions and 14 deletions

View File

@ -50,10 +50,15 @@ public:
CANCELED
};
typedef MediaPromise<nsRefPtr<AudioData>, NotDecodedReason> AudioDataPromise;
typedef MediaPromise<nsRefPtr<VideoData>, NotDecodedReason> VideoDataPromise;
typedef MediaPromise<int64_t, nsresult> SeekPromise;
typedef MediaPromise<MediaData::Type, WaitForDataRejectValue> WaitForDataPromise;
typedef MediaPromise<nsRefPtr<AudioData>, NotDecodedReason, /* IsExclusive = */ true> AudioDataPromise;
typedef MediaPromise<nsRefPtr<VideoData>, NotDecodedReason, /* IsExclusive = */ true> VideoDataPromise;
typedef MediaPromise<int64_t, nsresult, /* IsExclusive = */ true> SeekPromise;
// Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
// But in the current architecture it's only ever used exclusively (by MDSM),
// so we mark it that way to verify our assumptions. If you have a use-case
// for multiple WaitForData consumers, feel free to flip the exclusivity here.
typedef MediaPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)

View File

@ -45,11 +45,11 @@ nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRun
* callbacks to be invoked (asynchronously, on a specified thread) when the
* request is either completed (resolved) or cannot be completed (rejected).
*
* By default, resolve and reject callbacks are always invoked on the same thread
* where Then() was invoked.
* When IsExclusive is true, the MediaPromise does a release-mode assertion that
* there is at most one call to either Then(...) or ChainTo(...).
*/
template<typename T> class MediaPromiseHolder;
template<typename ResolveValueT, typename RejectValueT>
template<typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MediaPromise
{
public:
@ -60,24 +60,23 @@ public:
explicit MediaPromise(const char* aCreationSite)
: mCreationSite(aCreationSite)
, mMutex("MediaPromise Mutex")
, mHaveConsumer(false)
{
PROMISE_LOG("%s creating MediaPromise (%p)", mCreationSite, this);
}
static nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>>
static nsRefPtr<MediaPromise>
CreateAndResolve(ResolveValueType aResolveValue, const char* aResolveSite)
{
nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>> p =
new MediaPromise<ResolveValueT, RejectValueT>(aResolveSite);
nsRefPtr<MediaPromise> p = new MediaPromise(aResolveSite);
p->Resolve(aResolveValue, aResolveSite);
return p;
}
static nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>>
static nsRefPtr<MediaPromise>
CreateAndReject(RejectValueType aRejectValue, const char* aRejectSite)
{
nsRefPtr<MediaPromise<ResolveValueT, RejectValueT>> p =
new MediaPromise<ResolveValueT, RejectValueT>(aRejectSite);
nsRefPtr<MediaPromise> p = new MediaPromise(aRejectSite);
p->Reject(aRejectValue, aRejectSite);
return p;
}
@ -246,6 +245,8 @@ public:
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
mHaveConsumer = true;
ThenValueBase* thenValue = new ThenValue<TargetType, ThisType, ResolveMethodType,
RejectMethodType>(aResponseTarget, aThisVal,
aResolveMethod, aRejectMethod,
@ -262,6 +263,8 @@ public:
void ChainTo(already_AddRefed<MediaPromise> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(!IsExclusive || !mHaveConsumer);
mHaveConsumer = true;
nsRefPtr<MediaPromise> chainedPromise = aChainedPromise;
PROMISE_LOG("%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]",
aCallSite, this, chainedPromise.get(), (int) IsPending());
@ -330,6 +333,7 @@ protected:
Maybe<RejectValueType> mRejectValue;
nsTArray<ThenValueBase*> mThenValues;
nsTArray<nsRefPtr<MediaPromise>> mChainedPromises;
bool mHaveConsumer;
};
/*

View File

@ -20,7 +20,7 @@ namespace mozilla {
class SharedThreadPool;
typedef MediaPromise<bool, bool> ShutdownPromise;
typedef MediaPromise<bool, bool, false> ShutdownPromise;
// Abstracts executing runnables in order in a thread pool. The runnables
// dispatched to the MediaTaskQueue will be executed in the order in which