Bug 1157803 - Support connect-during-initialization for mirrors. r=jww
authorBobby Holley <bobbyholley@gmail.com>
Fri, 24 Apr 2015 20:23:04 -0700
changeset 241528 219435f463d2ea6d74b3ae57f04de23010c301f9
parent 241527 4a2c2ef2e24a0d687ce8fb400b1315bc41db3845
child 241529 4a072723d1d9bc0862ff7e832be5a0d86a6cbbda
push id28665
push userkwierso@gmail.com
push dateWed, 29 Apr 2015 23:43:43 +0000
treeherdermozilla-central@a86ed85747d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjww
bugs1157803
milestone40.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 1157803 - Support connect-during-initialization for mirrors. r=jww The MDSM is constructed and destroyed on the main thread, but runs most everything else on the task queue. So we need to bend the rules a bit here to conveniently connect its mirrors during construction.
dom/media/StateMirroring.h
--- a/dom/media/StateMirroring.h
+++ b/dom/media/StateMirroring.h
@@ -263,20 +263,25 @@ private:
  * breaking the inherent cycle between Mirror<T> and Canonical<T>.
  */
 template<typename T>
 class Mirror : public AbstractMirror<T>, public WatchTarget
 {
 public:
   using AbstractMirror<T>::OwnerThread;
 
-  Mirror(AbstractThread* aThread, const T& aInitialValue, const char* aName)
+  Mirror(AbstractThread* aThread, const T& aInitialValue, const char* aName,
+         AbstractCanonical<T>* aCanonical)
     : AbstractMirror<T>(aThread), WatchTarget(aName), mValue(aInitialValue)
   {
     MIRROR_LOG("%s [%p] initialized", mName, this);
+
+    if (aCanonical) {
+      ConnectInternal(aCanonical);
+    }
   }
 
   operator const T&()
   {
     MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
     return mValue;
   }
 
@@ -295,25 +300,34 @@ public:
     MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
     mCanonical = nullptr;
   }
 
   bool IsConnected() const { return !!mCanonical; }
 
   void Connect(AbstractCanonical<T>* aCanonical)
   {
+    MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
+    ConnectInternal(aCanonical);
+  }
+
+private:
+  // We separate the guts of Connect into a helper so that we can call it from
+  // initialization while not necessarily on the owner thread.
+  void ConnectInternal(AbstractCanonical<T>* aCanonical)
+  {
     MIRROR_LOG("%s [%p] Connecting to %p", mName, this, aCanonical);
-    MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
     MOZ_ASSERT(!IsConnected());
 
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<StorensRefPtrPassByPtr<AbstractMirror<T>>>
                                 (aCanonical, &AbstractCanonical<T>::AddMirror, this);
     aCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
     mCanonical = aCanonical;
   }
+public:
 
   void DisconnectIfConnected()
   {
     MOZ_ASSERT(OwnerThread()->IsCurrentThreadIn());
     if (!IsConnected()) {
       return;
     }
 
@@ -331,19 +345,20 @@ public:
     ~Holder()
     {
       MOZ_DIAGNOSTIC_ASSERT(mMirror, "Should have initialized me");
       mMirror->DisconnectIfConnected();
     }
 
     // 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)
+    void Init(AbstractThread* aThread, const T& aInitialValue, const char* aName,
+              AbstractCanonical<T>* aCanonical = nullptr)
     {
-      mMirror = new Mirror<T>(aThread, aInitialValue, aName);
+      mMirror = new Mirror<T>(aThread, aInitialValue, aName, aCanonical);
     }
 
     // Forward control operations to the Mirror<T>.
     void Connect(AbstractCanonical<T>* aCanonical) { mMirror->Connect(aCanonical); }
     void DisconnectIfConnected() { mMirror->DisconnectIfConnected(); }
 
     // Access to the Mirror<T>.
     operator Mirror<T>&() { return *mMirror; }