--- a/dom/media/systemservices/MediaUtils.h
+++ b/dom/media/systemservices/MediaUtils.h
@@ -2,17 +2,22 @@
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_MediaUtils_h
#define mozilla_MediaUtils_h
+#include "AutoTaskQueue.h"
#include "mozilla/Assertions.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/MozPromise.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/SharedThreadPool.h"
#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsIAsyncShutdown.h"
#include "nsISupportsImpl.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace media {
@@ -405,12 +410,128 @@ private:
{
nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
barrier->RemoveBlocker(mBlocker);
}
nsCOMPtr<nsIAsyncShutdownBlocker> mBlocker;
};
+/**
+ * Await convenience methods to block until the promise has been resolved or
+ * rejected. The Resolve/Reject functions, while called on a different thread,
+ * would be running just as on the current thread thanks to the memory barrier
+ * provided by the monitor.
+ * For now Await can only be used with an exclusive MozPromise if passed a
+ * Resolve/Reject function.
+ */
+template<typename ResolveValueType,
+ typename RejectValueType,
+ typename ResolveFunction,
+ typename RejectFunction>
+void
+Await(
+ RefPtr<MozPromise<ResolveValueType, RejectValueType, true>> aPromise,
+ ResolveFunction&& aResolveFunction,
+ RejectFunction&& aRejectFunction)
+{
+ Monitor mon(__func__);
+ RefPtr<AutoTaskQueue> taskQueue = new AutoTaskQueue(
+ SharedThreadPool::Get(NS_LITERAL_CSTRING("AwaitMozPromise")));
+ bool done = false;
+
+ aPromise->Then(taskQueue,
+ __func__,
+ [&](ResolveValueType&& aResolveValue) {
+ MonitorAutoLock lock(mon);
+ aResolveFunction(Forward<ResolveValueType>(aResolveValue));
+ done = true;
+ mon.Notify();
+ },
+ [&](RejectValueType&& aRejectValue) {
+ MonitorAutoLock lock(mon);
+ aRejectFunction(Forward<RejectValueType>(aRejectValue));
+ done = true;
+ mon.Notify();
+ });
+
+ MonitorAutoLock lock(mon);
+ while (!done) {
+ mon.Wait();
+ }
+}
+
+template<typename ResolveValueType, typename RejectValueType, bool Excl>
+typename MozPromise<ResolveValueType, RejectValueType, Excl>::
+ ResolveOrRejectValue
+Await(RefPtr<MozPromise<ResolveValueType, RejectValueType, Excl>> aPromise)
+{
+ Monitor mon(__func__);
+ RefPtr<AutoTaskQueue> taskQueue = new AutoTaskQueue(
+ SharedThreadPool::Get(NS_LITERAL_CSTRING("AwaitMozPromise")));
+ bool done = false;
+
+ typename MozPromise<ResolveValueType, RejectValueType, Excl>::ResolveOrRejectValue val;
+ aPromise->Then(taskQueue,
+ __func__,
+ [&](ResolveValueType aResolveValue) {
+ val.SetResolve(Move(aResolveValue));
+ MonitorAutoLock lock(mon);
+ done = true;
+ mon.Notify();
+ },
+ [&](RejectValueType aRejectValue) {
+ val.SetReject(Move(aRejectValue));
+ MonitorAutoLock lock(mon);
+ done = true;
+ mon.Notify();
+ });
+
+ MonitorAutoLock lock(mon);
+ while (!done) {
+ mon.Wait();
+ }
+
+ return val;
+}
+
+/**
+ * Similar to Await, takes an array of promises of the same type.
+ * MozPromise::All is used to handle the resolution/rejection of the promises.
+ */
+template<typename ResolveValueType,
+ typename RejectValueType,
+ typename ResolveFunction,
+ typename RejectFunction>
+void
+AwaitAll(nsTArray<RefPtr<MozPromise<ResolveValueType, RejectValueType, true>>>&
+ aPromises,
+ ResolveFunction&& aResolveFunction,
+ RejectFunction&& aRejectFunction)
+{
+ typedef MozPromise<ResolveValueType, RejectValueType, true> Promise;
+ RefPtr<AutoTaskQueue> taskQueue = new AutoTaskQueue(
+ SharedThreadPool::Get(NS_LITERAL_CSTRING("AwaitMozPromise")));
+ RefPtr<typename Promise::AllPromiseType> p = Promise::All(taskQueue, aPromises);
+ Await(p, Move(aResolveFunction), Move(aRejectFunction));
+}
+
+// Note: only works with exclusive MozPromise, as Promise::All would attempt
+// to perform copy of nsTArrays which are disallowed.
+template<typename ResolveValueType, typename RejectValueType>
+typename MozPromise<ResolveValueType,
+ RejectValueType,
+ true>::AllPromiseType::ResolveOrRejectValue
+AwaitAll(nsTArray<RefPtr<MozPromise<ResolveValueType, RejectValueType, true>>>&
+ aPromises)
+{
+ typedef MozPromise<ResolveValueType, RejectValueType, true> Promise;
+ RefPtr<AutoTaskQueue> taskQueue = new AutoTaskQueue(
+ SharedThreadPool::Get(NS_LITERAL_CSTRING("AwaitMozPromise")));
+ RefPtr<typename Promise::AllPromiseType> p =
+ Promise::All(taskQueue, aPromises);
+ return Await(p);
+}
+
} // namespace media
} // namespace mozilla
#endif // mozilla_MediaUtils_h