Remove monitor-related boilerplate in ImageBridgeChild.cpp. (bug 1300050, r=mattwoodrow)
☠☠ backed out by 16cec3bfe114 ☠ ☠
authorDavid Anderson <danderson@mozilla.com>
Tue, 06 Sep 2016 16:37:01 -0700
changeset 312926 4bc68896953392f4e053ceae4eb11343b0aa973d
parent 312925 4959bbdb0d99480d556b3738a1bdfb22b371c485
child 312927 16cec3bfe114fb9c5ca00500d792aa5ea048ca0e
push id30665
push usercbook@mozilla.com
push dateWed, 07 Sep 2016 15:20:43 +0000
treeherdermozilla-central@95acb9299faf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1300050
milestone51.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
Remove monitor-related boilerplate in ImageBridgeChild.cpp. (bug 1300050, r=mattwoodrow)
gfx/layers/ipc/ImageBridgeChild.cpp
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -396,20 +396,68 @@ static Thread *sImageBridgeChildThread =
 
 void
 ImageBridgeChild::FallbackDestroyActors() {
   if (mTxn && !mTxn->mDestroyedActors.IsEmpty()) {
     mTxn->FallbackDestroyActors();
   }
 }
 
+// Helper that creates a monitor and a "done" flag, then enters the monitor.
+// This can go away when we switch ImageBridge to an XPCOM thread.
+class MOZ_STACK_CLASS SynchronousTask
+{
+  friend class AutoCompleteTask;
+
+public:
+  SynchronousTask(const char* name)
+   : mMonitor(name),
+     mAutoEnter(mMonitor),
+     mDone(false)
+  {}
+
+  void Wait() {
+    while (!mDone) {
+      mMonitor.Wait();
+    }
+  }
+
+private:
+  void Complete() {
+    mDone = true;
+    mMonitor.NotifyAll();
+  }
+
+private:
+  ReentrantMonitor mMonitor;
+  ReentrantMonitorAutoEnter mAutoEnter;
+  bool mDone;
+};
+
+class MOZ_STACK_CLASS AutoCompleteTask
+{
+public:
+  AutoCompleteTask(SynchronousTask* aTask)
+   : mTask(aTask),
+     mAutoEnter(aTask->mMonitor)
+  {
+  }
+  ~AutoCompleteTask() {
+    mTask->Complete();
+  }
+
+private:
+  SynchronousTask* mTask;
+  ReentrantMonitorAutoEnter mAutoEnter;
+};
+
 // dispatched function
-static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
+static void ImageBridgeShutdownStep1(SynchronousTask* aTask)
 {
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+  AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(InImageBridgeChildThread(),
              "Should be in ImageBridgeChild thread.");
 
   MediaSystemResourceManager::Shutdown();
 
   if (sImageBridgeChildSingleton) {
     // Force all managed protocols to shut themselves down cleanly
@@ -431,61 +479,50 @@ static void ImageBridgeShutdownStep1(Ree
     }
     sImageBridgeChildSingleton->FallbackDestroyActors();
 
     sImageBridgeChildSingleton->SendWillClose();
     sImageBridgeChildSingleton->MarkShutDown();
     // From now on, no message can be sent through the image bridge from the
     // client side except the final Stop message.
   }
-
-  *aDone = true;
-  aBarrier->NotifyAll();
 }
 
 // dispatched function
-static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
+static void
+ImageBridgeShutdownStep2(SynchronousTask* aTask)
 {
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+  AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(InImageBridgeChildThread(),
              "Should be in ImageBridgeChild thread.");
 
   sImageBridgeChildSingleton->Close();
-
-  *aDone = true;
-  aBarrier->NotifyAll();
 }
 
 /* static */ void
-CreateImageClientSync(RefPtr<ImageBridgeChild> aChild,
+CreateImageClientSync(SynchronousTask* aTask,
+                      RefPtr<ImageBridgeChild> aChild,
                       RefPtr<ImageClient>* result,
-                      ReentrantMonitor* barrier,
                       CompositableType aType,
                       ImageContainer* aImageContainer,
-                      ImageContainerChild* aContainerChild,
-                      bool *aDone)
+                      ImageContainerChild* aContainerChild)
 {
-  ReentrantMonitorAutoEnter autoMon(*barrier);
+  AutoCompleteTask complete(aTask);
   *result = aChild->CreateImageClientNow(aType, aImageContainer, aContainerChild);
-  *aDone = true;
-  barrier->NotifyAll();
 }
 
 // dispatched function
-static void CreateCanvasClientSync(ReentrantMonitor* aBarrier,
+static void CreateCanvasClientSync(SynchronousTask* aTask,
                                    CanvasClient::CanvasClientType aType,
                                    TextureFlags aFlags,
-                                   RefPtr<CanvasClient>* const outResult,
-                                   bool* aDone)
+                                   RefPtr<CanvasClient>* const outResult)
 {
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+  AutoCompleteTask complete(aTask);
   *outResult = sImageBridgeChildSingleton->CreateCanvasClientNow(aType, aFlags);
-  *aDone = true;
-  aBarrier->NotifyAll();
 }
 
 static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
 {
   MessageLoop *parentMsgLoop = parent->GetMessageLoop();
   ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
   child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
 }
@@ -662,104 +699,92 @@ void ImageBridgeChild::DispatchImageClie
     return;
   }
 
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     NewRunnableFunction(&UpdateImageClientNow,
       RefPtr<ImageClient>(aClient), RefPtr<ImageContainer>(aContainer)));
 }
 
-static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper,
-                                          ReentrantMonitor* aBarrier,
-                                          bool* const outDone)
+static void
+UpdateAsyncCanvasRendererSync(SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper)
 {
+  AutoCompleteTask complete(aTask);
+
   ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper);
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *outDone = true;
-  aBarrier->NotifyAll();
 }
 
 // static
 void ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
 {
   aWrapper->GetCanvasClient()->UpdateAsync(aWrapper);
 
   if (InImageBridgeChildThread()) {
     UpdateAsyncCanvasRendererNow(aWrapper);
     return;
   }
 
-  ReentrantMonitor barrier("UpdateAsyncCanvasRenderer Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
+  SynchronousTask task("UpdateAsyncCanvasRenderer Lock");
 
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    NewRunnableFunction(&UpdateAsyncCanvasRendererSync, aWrapper, &barrier, &done));
+    NewRunnableFunction(&UpdateAsyncCanvasRendererSync, &task, aWrapper));
 
-  // should stop the thread until the CanvasClient has been created on
-  // the other thread
-  while (!done) {
-    barrier.Wait();
-  }
+  task.Wait();
 }
 
 // static
 void ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
 {
   MOZ_ASSERT(aWrapper);
   sImageBridgeChildSingleton->BeginTransaction();
   aWrapper->GetCanvasClient()->Updated();
   sImageBridgeChildSingleton->EndTransaction();
 }
 
-static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
-                               RefPtr<AsyncTransactionWaiter>&& aWaiter,
-                               ReentrantMonitor* aBarrier,
-                               bool* const outDone)
+static void
+FlushAllImagesSync(SynchronousTask* aTask,
+                   ImageClient* aClient,
+                   ImageContainer* aContainer,
+                   RefPtr<AsyncTransactionWaiter>&& aWaiter)
 {
 #ifdef MOZ_WIDGET_GONK
   MOZ_ASSERT(aWaiter);
 #else
   MOZ_ASSERT(!aWaiter);
 #endif
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+
+  AutoCompleteTask complete(aTask);
 
   if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
     // How sad. If we get into this branch it means that the ImageBridge
     // got destroyed between the time we ImageBridgeChild::FlushAllImage
     // was called on some thread, and the time this function was proxied
     // to the ImageBridge thread. ImageBridge gets destroyed way to late
     // in the shutdown of gecko for this to be happening for a good reason.
     NS_WARNING("Something is holding on to graphics resources after the shutdown"
                "of the graphics subsystem!");
 #ifdef MOZ_WIDGET_GONK
     aWaiter->DecrementWaitCount();
 #endif
-
-    *outDone = true;
-    aBarrier->NotifyAll();
     return;
   }
   MOZ_ASSERT(aClient);
   sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer) {
     aContainer->ClearImagesFromImageBridge();
   }
   aClient->FlushAllImages(aWaiter);
   sImageBridgeChildSingleton->EndTransaction();
   // This decrement is balanced by the increment in FlushAllImages.
   // If any AsyncTransactionTrackers were created by FlushAllImages and attached
   // to aWaiter, aWaiter will not complete until those trackers all complete.
   // Otherwise, aWaiter will be ready to complete now.
 #ifdef MOZ_WIDGET_GONK
   aWaiter->DecrementWaitCount();
 #endif
-  *outDone = true;
-  aBarrier->NotifyAll();
 }
 
 // static
 void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
                                       ImageContainer* aContainer)
 {
   if (!IsCreated() || IsShutDown()) {
     return;
@@ -767,32 +792,28 @@ void ImageBridgeChild::FlushAllImages(Im
   MOZ_ASSERT(aClient);
   MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   MOZ_ASSERT(!InImageBridgeChildThread());
   if (InImageBridgeChildThread()) {
     NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
     return;
   }
 
-  ReentrantMonitor barrier("FlushAllImages Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
+  SynchronousTask task("FlushAllImages Lock");
 
   RefPtr<AsyncTransactionWaiter> waiter;
 #ifdef MOZ_WIDGET_GONK
   waiter = new AsyncTransactionWaiter();
   // This increment is balanced by the decrement in FlushAllImagesSync
   waiter->IncrementWaitCount();
 #endif
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, waiter, &barrier, &done));
+    NewRunnableFunction(&FlushAllImagesSync, &task, aClient, aContainer, waiter));
 
-  while (!done) {
-    barrier.Wait();
-  }
+  task.Wait();
 
 #ifdef MOZ_WIDGET_GONK
   waiter->WaitComplete();
 #endif
 }
 
 void
 ImageBridgeChild::BeginTransaction()
@@ -896,37 +917,31 @@ void ImageBridgeChild::ShutDown()
   MOZ_ASSERT(NS_IsMainThread());
 
   sIsShutDown = true;
 
   if (ImageBridgeChild::IsCreated()) {
     MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
 
     {
-      ReentrantMonitor barrier("ImageBridge ShutdownStep1 lock");
-      ReentrantMonitorAutoEnter autoMon(barrier);
+      SynchronousTask task("ImageBridge ShutdownStep1 lock");
 
-      bool done = false;
       sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-                      NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done));
-      while (!done) {
-        barrier.Wait();
-      }
+                      NewRunnableFunction(&ImageBridgeShutdownStep1, &task));
+
+      task.Wait();
     }
 
     {
-      ReentrantMonitor barrier("ImageBridge ShutdownStep2 lock");
-      ReentrantMonitorAutoEnter autoMon(barrier);
+      SynchronousTask task("ImageBridge ShutdownStep2 lock");
 
-      bool done = false;
       sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-                      NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done));
-      while (!done) {
-        barrier.Wait();
-      }
+                      NewRunnableFunction(&ImageBridgeShutdownStep2, &task));
+
+      task.Wait();
     }
 
     sImageBridgeChildSingleton = nullptr;
 
     delete sImageBridgeChildThread;
     sImageBridgeChildThread = nullptr;
   }
 }
@@ -1001,29 +1016,24 @@ RefPtr<ImageClient>
 ImageBridgeChild::CreateImageClient(CompositableType aType,
                                     ImageContainer* aImageContainer,
                                     ImageContainerChild* aContainerChild)
 {
   if (InImageBridgeChildThread()) {
     return CreateImageClientNow(aType, aImageContainer, aContainerChild);
   }
 
-  ReentrantMonitor barrier("CreateImageClient Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
+  SynchronousTask task("CreateImageClient Lock");
 
   RefPtr<ImageClient> result = nullptr;
   GetMessageLoop()->PostTask(
-      NewRunnableFunction(&CreateImageClientSync, this, &result, &barrier, aType,
-                          aImageContainer, aContainerChild, &done));
-  // should stop the thread until the ImageClient has been created on
-  // the other thread
-  while (!done) {
-    barrier.Wait();
-  }
+      NewRunnableFunction(&CreateImageClientSync, &task, this, &result, aType,
+                          aImageContainer, aContainerChild));
+
+  task.Wait();
 
   return result;
 }
 
 RefPtr<ImageClient>
 ImageBridgeChild::CreateImageClientNow(CompositableType aType,
                                        ImageContainer* aImageContainer,
                                        ImageContainerChild* aContainerChild)
@@ -1046,28 +1056,25 @@ ImageBridgeChild::CreateImageClientNow(C
 
 already_AddRefed<CanvasClient>
 ImageBridgeChild::CreateCanvasClient(CanvasClient::CanvasClientType aType,
                                      TextureFlags aFlag)
 {
   if (InImageBridgeChildThread()) {
     return CreateCanvasClientNow(aType, aFlag);
   }
-  ReentrantMonitor barrier("CreateCanvasClient Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
+
+  SynchronousTask task("CreateCanvasClient Lock");
 
   RefPtr<CanvasClient> result = nullptr;
   GetMessageLoop()->PostTask(NewRunnableFunction(&CreateCanvasClientSync,
-                                 &barrier, aType, aFlag, &result, &done));
-  // should stop the thread until the CanvasClient has been created on the
-  // other thread
-  while (!done) {
-    barrier.Wait();
-  }
+                                 &task, aType, aFlag, &result));
+
+  task.Wait();
+
   return result.forget();
 }
 
 already_AddRefed<CanvasClient>
 ImageBridgeChild::CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
                                         TextureFlags aFlag)
 {
   RefPtr<CanvasClient> client
@@ -1112,98 +1119,80 @@ struct AllocShmemParams {
   RefPtr<ISurfaceAllocator> mAllocator;
   size_t mSize;
   ipc::SharedMemory::SharedMemoryType mType;
   ipc::Shmem* mShmem;
   bool mUnsafe;
   bool mSuccess;
 };
 
-static void ProxyAllocShmemNow(AllocShmemParams* aParams,
-                               ReentrantMonitor* aBarrier,
-                               bool* aDone)
+static void
+ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams)
 {
+  AutoCompleteTask complete(aTask);
+
   MOZ_ASSERT(aParams);
-  MOZ_ASSERT(aDone);
-  MOZ_ASSERT(aBarrier);
 
   auto shmAllocator = aParams->mAllocator->AsShmemAllocator();
   if (aParams->mUnsafe) {
     aParams->mSuccess = shmAllocator->AllocUnsafeShmem(aParams->mSize,
                                                        aParams->mType,
                                                        aParams->mShmem);
   } else {
     aParams->mSuccess = shmAllocator->AllocShmem(aParams->mSize,
                                                  aParams->mType,
                                                  aParams->mShmem);
   }
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *aDone = true;
-  aBarrier->NotifyAll();
 }
 
 bool
 ImageBridgeChild::DispatchAllocShmemInternal(size_t aSize,
                                              SharedMemory::SharedMemoryType aType,
                                              ipc::Shmem* aShmem,
                                              bool aUnsafe)
 {
-  ReentrantMonitor barrier("AllocatorProxy alloc");
-  ReentrantMonitorAutoEnter autoMon(barrier);
+  SynchronousTask task("AllocatorProxy alloc");
 
   AllocShmemParams params = {
     this, aSize, aType, aShmem, aUnsafe, true
   };
-  bool done = false;
 
   GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyAllocShmemNow,
-                                                 &params,
-                                                 &barrier,
-                                                 &done));
-  while (!done) {
-    barrier.Wait();
-  }
+                                                 &task, &params));
+
+  task.Wait();
+
   return params.mSuccess;
 }
 
-static void ProxyDeallocShmemNow(ISurfaceAllocator* aAllocator,
-                                 ipc::Shmem* aShmem,
-                                 ReentrantMonitor* aBarrier,
-                                 bool* aDone)
+static void ProxyDeallocShmemNow(SynchronousTask* aTask,
+                                 ISurfaceAllocator* aAllocator,
+                                 ipc::Shmem* aShmem)
 {
+  AutoCompleteTask complete(aTask);
+
   MOZ_ASSERT(aShmem);
-  MOZ_ASSERT(aDone);
-  MOZ_ASSERT(aBarrier);
 
   aAllocator->AsShmemAllocator()->DeallocShmem(*aShmem);
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *aDone = true;
-  aBarrier->NotifyAll();
 }
 
 void
 ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
   if (InImageBridgeChildThread()) {
     PImageBridgeChild::DeallocShmem(aShmem);
   } else {
-    ReentrantMonitor barrier("AllocatorProxy Dealloc");
-    ReentrantMonitorAutoEnter autoMon(barrier);
+    SynchronousTask task("AllocatorProxy Dealloc");
 
-    bool done = false;
     GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyDeallocShmemNow,
+                                                   &task,
                                                    this,
-                                                   &aShmem,
-                                                   &barrier,
-                                                   &done));
-    while (!done) {
-      barrier.Wait();
-    }
+                                                   &aShmem));
+
+    task.Wait();
   }
 }
 
 PTextureChild*
 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial)