Bug 1366316 - Separate thread for IPCBlobInputStream actors - part 5 - WorkerHolder, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 31 May 2017 07:41:11 +0200
changeset 409637 fd22c45d4adaf340a733457443a686bd136012d5
parent 409636 3965a5c72ea35aede1a3db86556713fbc85b6d84
child 409638 14a2665a64f6e78b7c470a3eb0635e491660955a
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1366316
milestone55.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 1366316 - Separate thread for IPCBlobInputStream actors - part 5 - WorkerHolder, r=smaug WorkerHolder must be released after the migration.
dom/file/ipc/IPCBlobInputStreamChild.cpp
--- a/dom/file/ipc/IPCBlobInputStreamChild.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp
@@ -3,18 +3,19 @@
 /* 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/. */
 
 #include "IPCBlobInputStreamChild.h"
 #include "IPCBlobInputStreamThread.h"
 
 #include "mozilla/ipc/IPCStreamUtils.h"
+#include "WorkerHolder.h"
 #include "WorkerPrivate.h"
-#include "WorkerHolder.h"
+#include "WorkerRunnable.h"
 
 namespace mozilla {
 namespace dom {
 
 using namespace workers;
 
 namespace {
 
@@ -86,31 +87,45 @@ public:
 private:
   RefPtr<IPCBlobInputStream> mDestinationStream;
   nsCOMPtr<nsIInputStream> mCreatedStream;
 };
 
 class IPCBlobInputStreamWorkerHolder final : public WorkerHolder
 {
 public:
-  explicit IPCBlobInputStreamWorkerHolder(IPCBlobInputStreamChild* aActor)
-    : mActor(aActor)
-  {}
-
   bool Notify(Status aStatus) override
   {
-    if (aStatus > Running) {
-      mActor->Shutdown();
-      // After this the WorkerHolder is gone.
-    }
+    // We must keep the worker alive until the migration is completed.
     return true;
   }
+};
+
+class ReleaseWorkerHolderRunnable final : public CancelableRunnable
+{
+public:
+  explicit ReleaseWorkerHolderRunnable(UniquePtr<workers::WorkerHolder>&& aWorkerHolder)
+    : mWorkerHolder(Move(aWorkerHolder))
+  {}
+
+  NS_IMETHOD
+  Run() override
+  {
+    mWorkerHolder = nullptr;
+    return NS_OK;
+  }
+
+  nsresult
+  Cancel() override
+  {
+    return Run();
+  }
 
 private:
-  RefPtr<IPCBlobInputStreamChild> mActor;
+  UniquePtr<workers::WorkerHolder> mWorkerHolder;
 };
 
 } // anonymous
 
 IPCBlobInputStreamChild::IPCBlobInputStreamChild(const nsID& aID,
                                                  uint64_t aSize)
   : mMutex("IPCBlobInputStreamChild::mMutex")
   , mID(aID)
@@ -119,17 +134,17 @@ IPCBlobInputStreamChild::IPCBlobInputStr
   , mOwningThread(NS_GetCurrentThread())
 {
   // If we are running in a worker, we need to send a Close() to the parent side
   // before the thread is released.
   if (!NS_IsMainThread()) {
     WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     if (workerPrivate) {
       UniquePtr<WorkerHolder> workerHolder(
-        new IPCBlobInputStreamWorkerHolder(this));
+        new IPCBlobInputStreamWorkerHolder());
       if (workerHolder->HoldWorker(workerPrivate, Canceling)) {
         mWorkerHolder.swap(workerHolder);
       }
     }
   }
 }
 
 IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
@@ -302,16 +317,22 @@ IPCBlobInputStreamChild::RecvStreamReady
 }
 
 void
 IPCBlobInputStreamChild::Migrated()
 {
   MutexAutoLock lock(mMutex);
   MOZ_ASSERT(mState == eInactiveMigrating);
 
+  if (mWorkerHolder) {
+    RefPtr<ReleaseWorkerHolderRunnable> runnable =
+      new ReleaseWorkerHolderRunnable(Move(mWorkerHolder));
+    mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  }
+
   mOwningThread = NS_GetCurrentThread();
   MOZ_ASSERT(IPCBlobInputStreamThread::IsOnFileThread(mOwningThread));
 
   // Maybe we have no reasons to keep this actor alive.
   if (mStreams.IsEmpty()) {
     mState = eInactive;
     SendClose();
     return;