Bug 1366316 - Separate thread for IPCBlobInputStream actors - part 2 - callback stored, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 31 May 2017 07:41:10 +0200
changeset 409634 432077ba9b7f109d0e123ae4852de30de9e8578b
parent 409633 59c54a18bf9532ccb206494646b59af56012df51
child 409635 c1b48496a0f39423b97304c01d855f0f361969b3
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 2 - callback stored, r=smaug
dom/file/ipc/IPCBlobInputStreamParent.cpp
dom/file/ipc/IPCBlobInputStreamStorage.cpp
dom/file/ipc/IPCBlobInputStreamStorage.h
--- a/dom/file/ipc/IPCBlobInputStreamParent.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamParent.cpp
@@ -30,17 +30,22 @@ IPCBlobInputStreamParent::Create(nsIInpu
 
   return new IPCBlobInputStreamParent(id, aSize, aManager);
 }
 
 /* static */ IPCBlobInputStreamParent*
 IPCBlobInputStreamParent::Create(const nsID& aID, uint64_t aSize,
                                  PBackgroundParent* aManager)
 {
-  return new IPCBlobInputStreamParent(aID, aSize, aManager);
+  IPCBlobInputStreamParent* actor =
+    new IPCBlobInputStreamParent(aID, aSize, aManager);
+
+  actor->mCallback = IPCBlobInputStreamStorage::Get()->TakeCallback(aID);
+
+  return actor;
 }
 
 IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID,
                                                    uint64_t aSize,
                                                    nsIContentParent* aManager)
   : mID(aID)
   , mSize(aSize)
   , mContentManager(aManager)
@@ -61,26 +66,35 @@ IPCBlobInputStreamParent::IPCBlobInputSt
 void
 IPCBlobInputStreamParent::ActorDestroy(IProtocol::ActorDestroyReason aReason)
 {
   MOZ_ASSERT(mContentManager || mPBackgroundManager);
 
   mContentManager = nullptr;
   mPBackgroundManager = nullptr;
 
-  if (!mMigrating) {
-    IPCBlobInputStreamStorage::Get()->ForgetStream(mID);
+  RefPtr<IPCBlobInputStreamParentCallback> callback;
+  mCallback.swap(callback);
+
+  RefPtr<IPCBlobInputStreamStorage> storage = IPCBlobInputStreamStorage::Get();
 
-    // TODO, this calllback must be migrated as well!
-    RefPtr<IPCBlobInputStreamParentCallback> callback;
-    mCallback.swap(callback);
+  if (mMigrating) {
+    if (callback && storage) {
+      // We need to assign this callback to the next parent.
+      IPCBlobInputStreamStorage::Get()->StoreCallback(mID, callback);
+    }
+    return;
+  }
 
-    if (callback) {
-      callback->ActorDestroyed(mID);
-    }
+  if (storage) {
+    storage->ForgetStream(mID);
+  }
+
+  if (callback) {
+    callback->ActorDestroyed(mID);
   }
 }
 
 void
 IPCBlobInputStreamParent::SetCallback(
                                     IPCBlobInputStreamParentCallback* aCallback)
 {
   MOZ_ASSERT(aCallback);
--- a/dom/file/ipc/IPCBlobInputStreamStorage.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamStorage.cpp
@@ -14,16 +14,19 @@
 namespace mozilla {
 namespace dom {
 
 namespace {
 StaticMutex gMutex;
 StaticRefPtr<IPCBlobInputStreamStorage> gStorage;
 }
 
+IPCBlobInputStreamStorage::IPCBlobInputStreamStorage()
+{}
+
 IPCBlobInputStreamStorage::~IPCBlobInputStreamStorage()
 {}
 
 /* static */ IPCBlobInputStreamStorage*
 IPCBlobInputStreamStorage::Get()
 {
   return gStorage;
 }
@@ -38,52 +41,83 @@ IPCBlobInputStreamStorage::Initialize()
 }
 
 void
 IPCBlobInputStreamStorage::AddStream(nsIInputStream* aInputStream,
                                      const nsID& aID)
 {
   MOZ_ASSERT(aInputStream);
 
+  StreamData* data = new StreamData();
+  data->mInputStream = aInputStream;
+
   mozilla::StaticMutexAutoLock lock(gMutex);
-  mStorage.Put(aID, aInputStream);
+  mStorage.Put(aID, data);
 }
 
 void
 IPCBlobInputStreamStorage::ForgetStream(const nsID& aID)
 {
   mozilla::StaticMutexAutoLock lock(gMutex);
   mStorage.Remove(aID);
 }
 
 void
 IPCBlobInputStreamStorage::GetStream(const nsID& aID,
                                      nsIInputStream** aInputStream)
 {
   mozilla::StaticMutexAutoLock lock(gMutex);
-  nsCOMPtr<nsIInputStream> stream = mStorage.Get(aID);
-  if (!stream) {
+  StreamData* data = mStorage.Get(aID);
+  if (!data) {
     *aInputStream = nullptr;
     return;
   }
 
   // We cannot return always the same inputStream because not all of them are
   // able to be reused. Better to clone them.
 
   nsCOMPtr<nsIInputStream> clonedStream;
   nsCOMPtr<nsIInputStream> replacementStream;
 
   nsresult rv =
-    NS_CloneInputStream(stream, getter_AddRefs(clonedStream),
+    NS_CloneInputStream(data->mInputStream, getter_AddRefs(clonedStream),
                         getter_AddRefs(replacementStream));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   if (replacementStream) {
-    mStorage.Put(aID, replacementStream);
+    data->mInputStream = replacementStream;
   }
 
   clonedStream.forget(aInputStream);
 }
 
+void
+IPCBlobInputStreamStorage::StoreCallback(const nsID& aID,
+                                         IPCBlobInputStreamParentCallback* aCallback)
+{
+  MOZ_ASSERT(aCallback);
+
+  mozilla::StaticMutexAutoLock lock(gMutex);
+  StreamData* data = mStorage.Get(aID);
+  if (data) {
+    MOZ_ASSERT(!data->mCallback);
+    data->mCallback = aCallback;
+  }
+}
+
+already_AddRefed<IPCBlobInputStreamParentCallback>
+IPCBlobInputStreamStorage::TakeCallback(const nsID& aID)
+{
+  mozilla::StaticMutexAutoLock lock(gMutex);
+  StreamData* data = mStorage.Get(aID);
+  if (!data) {
+    return nullptr;
+  }
+
+  RefPtr<IPCBlobInputStreamParentCallback> callback;
+  data->mCallback.swap(callback);
+  return callback.forget();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/file/ipc/IPCBlobInputStreamStorage.h
+++ b/dom/file/ipc/IPCBlobInputStreamStorage.h
@@ -3,25 +3,27 @@
 /* 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_dom_ipc_IPCBlobInputStreamStorage_h
 #define mozilla_dom_ipc_IPCBlobInputStreamStorage_h
 
 #include "mozilla/RefPtr.h"
-#include "nsInterfaceHashtable.h"
+#include "nsClassHashtable.h"
 #include "nsISupportsImpl.h"
 
 class nsIInputStream;
 struct nsID;
 
 namespace mozilla {
 namespace dom {
 
+class IPCBlobInputStreamParentCallback;
+
 class IPCBlobInputStreamStorage final
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IPCBlobInputStreamStorage);
 
   // This initializes the singleton and it must be called on the main-thread.
   static void
   Initialize();
@@ -33,18 +35,31 @@ public:
   AddStream(nsIInputStream* aInputStream, const nsID& aID);
 
   void
   ForgetStream(const nsID& aID);
 
   void
   GetStream(const nsID& aID, nsIInputStream** aInputStream);
 
+  void
+  StoreCallback(const nsID& aID, IPCBlobInputStreamParentCallback* aCallback);
+
+  already_AddRefed<IPCBlobInputStreamParentCallback>
+  TakeCallback(const nsID& aID);
+
 private:
+  IPCBlobInputStreamStorage();
   ~IPCBlobInputStreamStorage();
 
-  nsInterfaceHashtable<nsIDHashKey, nsIInputStream> mStorage;
+  struct StreamData
+  {
+    nsCOMPtr<nsIInputStream> mInputStream;
+    RefPtr<IPCBlobInputStreamParentCallback> mCallback;
+  };
+
+  nsClassHashtable<nsIDHashKey, StreamData> mStorage;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ipc_IPCBlobInputStreamStorage_h