Bug 1497175 - Remove media::Pledge. r=pehrsons
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 30 Nov 2018 05:15:00 +0000
changeset 508137 f4577848e2eeaa704731c9e3f3d69e7975b0bdfd
parent 508136 116803bacea74c7164b1cd9be3d10d3c185c09b7
child 508138 8a78c4c56019d4891f24998613f80de5f894f340
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1497175
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1497175 - Remove media::Pledge. r=pehrsons Differential Revision: https://phabricator.services.mozilla.com/D8011
dom/media/systemservices/MediaParent.h
dom/media/systemservices/MediaUtils.h
--- a/dom/media/systemservices/MediaParent.h
+++ b/dom/media/systemservices/MediaParent.h
@@ -62,18 +62,16 @@ class Parent : public RefCountedParent, 
 
   Parent();
 
  private:
   virtual ~Parent();
 
   RefPtr<OriginKeyStore> mOriginKeyStore;
   bool mDestroyed;
-
-  CoatCheck<Pledge<nsCString>> mOutstandingPledges;
 };
 
 template <class Parent>
 mozilla::ipc::IPCResult IPCResult(Parent* aSelf, bool aSuccess);
 
 template <>
 inline mozilla::ipc::IPCResult IPCResult(Parent<PMediaParent>* aSelf,
                                          bool aSuccess) {
--- a/dom/media/systemservices/MediaUtils.h
+++ b/dom/media/systemservices/MediaUtils.h
@@ -19,134 +19,16 @@
 #include "nsISupportsImpl.h"
 #include "nsThreadUtils.h"
 
 class nsIEventTarget;
 
 namespace mozilla {
 namespace media {
 
-/*
- * media::Pledge - A promise-like pattern for c++ that takes lambda functions.
- *
- * Asynchronous APIs that proxy to another thread or to the chrome process and
- * back may find it useful to return a pledge to callers who then use
- * pledge.Then(func) to specify a lambda function to be invoked with the result
- * later back on this same thread.
- *
- * Callers will enjoy that lambdas allow "capturing" of local variables, much
- * like closures in JavaScript (safely by-copy by default).
- *
- * Callers will also enjoy that they do not need to be thread-safe (their code
- * runs on the same thread after all).
- *
- * Advantageously, pledges are non-threadsafe by design (because locking and
- * event queues are redundant). This means none of the lambdas you pass in,
- * or variables you lambda-capture into them, need be threasafe or support
- * threadsafe refcounting. After all, they'll run later on the same thread.
- *
- *   RefPtr<media::Pledge<Foo>> p = GetFooAsynchronously(); // returns a pledge
- *   p->Then([](const Foo& foo) {
- *     // use foo here (same thread. Need not be thread-safe!)
- *   });
- *
- * See media::CoatCheck below for an example of GetFooAsynchronously().
- */
-
-class PledgeBase {
- public:
-  NS_INLINE_DECL_REFCOUNTING(PledgeBase);
-
- protected:
-  virtual ~PledgeBase(){};
-};
-
-template <typename ValueType, typename ErrorType = nsresult>
-class Pledge : public PledgeBase {
-  // TODO: Remove workaround once mozilla allows std::function from <functional>
-  // wo/std::function support, do template + virtual trick to accept lambdas
-  class FunctorsBase {
-   public:
-    FunctorsBase() {}
-    virtual void Succeed(ValueType& result) = 0;
-    virtual void Fail(ErrorType& error) = 0;
-    virtual ~FunctorsBase(){};
-  };
-
- public:
-  explicit Pledge() : mDone(false), mRejected(false) {}
-  Pledge(const Pledge& aOther) = delete;
-  Pledge& operator=(const Pledge&) = delete;
-
-  template <typename OnSuccessType>
-  void Then(OnSuccessType&& aOnSuccess) {
-    Then(std::forward<OnSuccessType>(aOnSuccess), [](ErrorType&) {});
-  }
-
-  template <typename OnSuccessType, typename OnFailureType>
-  void Then(OnSuccessType&& aOnSuccess, OnFailureType&& aOnFailure) {
-    class Functors : public FunctorsBase {
-     public:
-      Functors(OnSuccessType&& aOnSuccessRef, OnFailureType&& aOnFailureRef)
-          : mOnSuccess(std::move(aOnSuccessRef)),
-            mOnFailure(std::move(aOnFailureRef)) {}
-
-      void Succeed(ValueType& result) { mOnSuccess(result); }
-      void Fail(ErrorType& error) { mOnFailure(error); };
-
-      OnSuccessType mOnSuccess;
-      OnFailureType mOnFailure;
-    };
-    mFunctors = MakeUnique<Functors>(std::forward<OnSuccessType>(aOnSuccess),
-                                     std::forward<OnFailureType>(aOnFailure));
-    if (mDone) {
-      if (!mRejected) {
-        mFunctors->Succeed(mValue);
-      } else {
-        mFunctors->Fail(mError);
-      }
-    }
-  }
-
-  void Resolve(const ValueType& aValue) {
-    mValue = aValue;
-    Resolve();
-  }
-
-  void Reject(ErrorType rv) {
-    if (!mDone) {
-      mDone = mRejected = true;
-      mError = rv;
-      if (mFunctors) {
-        mFunctors->Fail(mError);
-      }
-    }
-  }
-
- protected:
-  void Resolve() {
-    if (!mDone) {
-      mDone = true;
-      MOZ_ASSERT(!mRejected);
-      if (mFunctors) {
-        mFunctors->Succeed(mValue);
-      }
-    }
-  }
-
-  ValueType mValue;
-
- private:
-  ~Pledge(){};
-  bool mDone;
-  bool mRejected;
-  ErrorType mError;
-  UniquePtr<FunctorsBase> mFunctors;
-};
-
 /* media::NewRunnableFrom() - Create a Runnable from a lambda.
  *
  * Passing variables (closures) to an async function is clunky with Runnable:
  *
  *   void Foo()
  *   {
  *     class FooRunnable : public Runnable
  *     {
@@ -195,111 +77,16 @@ class LambdaRunnable : public Runnable {
 template <typename OnRunType>
 already_AddRefed<LambdaRunnable<OnRunType>> NewRunnableFrom(
     OnRunType&& aOnRun) {
   typedef LambdaRunnable<OnRunType> LambdaType;
   RefPtr<LambdaType> lambda = new LambdaType(std::forward<OnRunType>(aOnRun));
   return lambda.forget();
 }
 
-/* media::CoatCheck - There and back again. Park an object in exchange for an
- * id.
- *
- * A common problem with calling asynchronous functions that do work on other
- * threads or processes is how to pass in a heap object for use once the
- * function completes, without requiring that object to have threadsafe
- * refcounting, contain mutexes, be marshaled, or leak if things fail
- * (or worse, intermittent use-after-free because of lifetime issues).
- *
- * One solution is to set up a coat-check on the caller side, park your object
- * in exchange for an id, and send the id. Common in IPC, but equally useful
- * for same-process thread-hops, because by never leaving the thread there's
- * no need for objects to be threadsafe or use threadsafe refcounting. E.g.
- *
- *   class FooDoer
- *   {
- *     CoatCheck<Foo> mOutstandingFoos;
- *
- *   public:
- *     void DoFoo()
- *     {
- *       RefPtr<Foo> foo = new Foo();
- *       uint32_t requestId = mOutstandingFoos.Append(*foo);
- *       sChild->SendFoo(requestId);
- *     }
- *
- *     void RecvFooResponse(uint32_t requestId)
- *     {
- *       RefPtr<Foo> foo = mOutstandingFoos.Remove(requestId);
- *       if (foo) {
- *         // use foo
- *       }
- *     }
- *   };
- *
- * If you read media::Pledge earlier, here's how this is useful for pledges:
- *
- *   class FooGetter
- *   {
- *     CoatCheck<Pledge<Foo>> mOutstandingPledges;
- *
- *   public:
- *     already_addRefed<Pledge<Foo>> GetFooAsynchronously()
- *     {
- *       RefPtr<Pledge<Foo>> p = new Pledge<Foo>();
- *       uint32_t requestId = mOutstandingPledges.Append(*p);
- *       sChild->SendFoo(requestId);
- *       return p.forget();
- *     }
- *
- *     void RecvFooResponse(uint32_t requestId, const Foo& fooResult)
- *     {
- *       RefPtr<Foo> p = mOutstandingPledges.Remove(requestId);
- *       if (p) {
- *         p->Resolve(fooResult);
- *       }
- *     }
- *   };
- *
- * This helper is currently optimized for very small sets (i.e. not optimized).
- * It is also not thread-safe as the whole point is to stay on the same thread.
- */
-
-template <class T>
-class CoatCheck {
- public:
-  typedef std::pair<uint32_t, RefPtr<T>> Element;
-
-  uint32_t Append(T& t) {
-    uint32_t id = GetNextId();
-    mElements.AppendElement(Element(id, RefPtr<T>(&t)));
-    return id;
-  }
-
-  already_AddRefed<T> Remove(uint32_t aId) {
-    for (auto& element : mElements) {
-      if (element.first == aId) {
-        RefPtr<T> ref;
-        ref.swap(element.second);
-        mElements.RemoveElement(element);
-        return ref.forget();
-      }
-    }
-    MOZ_ASSERT_UNREACHABLE("Received id with no matching parked object!");
-    return nullptr;
-  }
-
- private:
-  static uint32_t GetNextId() {
-    static uint32_t counter = 0;
-    return ++counter;
-  };
-  AutoTArray<Element, 3> mElements;
-};
-
 /* media::Refcountable - Add threadsafe ref-counting to something that isn't.
  *
  * Often, reference counting is the most practical way to share an object with
  * another thread without imposing lifetime restrictions, even if there's
  * otherwise no concurrent access happening on the object.  For instance, an
  * algorithm on another thread may find it more expedient to modify a passed-in
  * object, rather than pass expensive copies back and forth.
  *