Bug 1648141 - IPCBlobInputStream to RemoteLazyInputStream - part 5 - thread, r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D80928
This commit is contained in:
Andrea Marchesini 2020-06-29 13:39:01 +00:00
Родитель 5fc1253731
Коммит c6e87ab4b6
12 изменённых файлов: 124 добавлений и 118 удалений

Просмотреть файл

@ -22,7 +22,6 @@ Compositor
Cookie
CrashRep Inject
DDMediaLogs
DOM File
DOMCacheThread
DataChannel IO
DataStorage
@ -64,6 +63,7 @@ ProcessHangMon
ProfSymbolTable
ProfilerChild
ProxyResolution
RemoteLzyStream
RWLockTester
RacingServMan
RemVidChild

Просмотреть файл

@ -6,7 +6,7 @@
#include "TemporaryFileBlobImpl.h"
#include "IPCBlobInputStreamThread.h"
#include "RemoteLazyInputStreamThread.h"
#include "nsFileStreams.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
@ -76,9 +76,9 @@ class TemporaryFileInputStream final : public nsFileInputStream {
}
~TemporaryFileInputStream() {
// Let's delete the file on the IPCBlob Thread.
RefPtr<IPCBlobInputStreamThread> thread =
IPCBlobInputStreamThread::GetOrCreate();
// Let's delete the file on the RemoteLazyInputStream Thread.
RefPtr<RemoteLazyInputStreamThread> thread =
RemoteLazyInputStreamThread::GetOrCreate();
if (NS_WARN_IF(!thread)) {
return;
}

Просмотреть файл

@ -11,7 +11,6 @@
#include "mozilla/net/SocketProcessParent.h"
#include "mozilla/SlicedInputStream.h"
#include "mozilla/NonBlockingAsyncInputStream.h"
#include "IPCBlobInputStreamThread.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIPipe.h"
@ -19,6 +18,7 @@
#include "nsStreamUtils.h"
#include "nsStringStream.h"
#include "RemoteLazyInputStreamStorage.h"
#include "RemoteLazyInputStreamThread.h"
namespace mozilla {
@ -804,8 +804,8 @@ nsresult IPCBlobInputStream::EnsureAsyncRemoteStream(
return rv;
}
RefPtr<IPCBlobInputStreamThread> thread =
IPCBlobInputStreamThread::GetOrCreate();
RefPtr<RemoteLazyInputStreamThread> thread =
RemoteLazyInputStreamThread::GetOrCreate();
if (NS_WARN_IF(!thread)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -137,8 +137,8 @@
* method will be forwarded to the 'real' stream ones. This means that the
* reading will be available.
*
* DOM-File Thread
* ~~~~~~~~~~~~~~~
* RemoteLazyInputStream Thread
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* RemoteLazyInputStreamChild actor can be created in any thread (sort of) and
* their top-level IPDL protocol is PBackground. These actors are wrapped by 1
@ -164,10 +164,10 @@
* 1. If RemoteLazyInputStreamChild actor is not already owned by DOM-File
* thread, it calls Send__delete__ in order to inform the parent side that we
* don't need this IPC channel on the current thread.
* 2. A new RemoteLazyInputStreamChild is created. IPCBlobInputStreamThread is
* used to assign this actor to the DOM-File thread.
* IPCBlobInputStreamThread::GetOrCreate() creates the DOM-File thread if it
* doesn't exist yet. Pending operations and IPCBlobInputStreams are moved
* 2. A new RemoteLazyInputStreamChild is created. RemoteLazyInputStreamThread
* is used to assign this actor to the DOM-File thread.
* RemoteLazyInputStreamThread::GetOrCreate() creates the DOM-File thread if
* it doesn't exist yet. Pending operations and IPCBlobInputStreams are moved
* onto the new actor.
* 3. RemoteLazyInputStreamParent::Recv__delete__ is called on the parent side
* and the parent actor is deleted. Doing this we don't remove the UUID from

Просмотреть файл

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteLazyInputStreamChild.h"
#include "IPCBlobInputStreamThread.h"
#include "RemoteLazyInputStreamThread.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/dom/WorkerCommon.h"
@ -205,14 +205,14 @@ RemoteLazyInputStreamChild::CreateStream() {
// The stream is active but maybe it is not running in the DOM-File thread.
// We should migrate it there.
if (mState == eActive &&
!IPCBlobInputStreamThread::IsOnFileEventTarget(mOwningEventTarget)) {
!RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget)) {
MOZ_ASSERT(mStreams.IsEmpty());
shouldMigrate = true;
mState = eActiveMigrating;
RefPtr<IPCBlobInputStreamThread> thread =
IPCBlobInputStreamThread::GetOrCreate();
RefPtr<RemoteLazyInputStreamThread> thread =
RemoteLazyInputStreamThread::GetOrCreate();
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
// Create a new actor object to connect to the target thread.
@ -412,7 +412,8 @@ void RemoteLazyInputStreamChild::Migrated() {
mWorkerRef = nullptr;
mOwningEventTarget = GetCurrentSerialEventTarget();
MOZ_ASSERT(IPCBlobInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
MOZ_ASSERT(
RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
// Maybe we have no reasons to keep this actor alive.
if (mStreams.IsEmpty()) {

Просмотреть файл

@ -4,7 +4,7 @@
* 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 "IPCBlobInputStreamThread.h"
#include "RemoteLazyInputStreamThread.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/StaticMutex.h"
@ -21,8 +21,8 @@ namespace dom {
namespace {
StaticMutex gIPCBlobThreadMutex;
StaticRefPtr<IPCBlobInputStreamThread> gIPCBlobThread;
StaticMutex gRemoteLazyThreadMutex;
StaticRefPtr<RemoteLazyInputStreamThread> gRemoteLazyThread;
bool gShutdownHasStarted = false;
class ThreadInitializeRunnable final : public Runnable {
@ -31,9 +31,9 @@ class ThreadInitializeRunnable final : public Runnable {
NS_IMETHOD
Run() override {
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
MOZ_ASSERT(gIPCBlobThread);
gIPCBlobThread->InitializeOnMainThread();
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
MOZ_ASSERT(gRemoteLazyThread);
gRemoteLazyThread->InitializeOnMainThread();
return NS_OK;
}
};
@ -72,10 +72,10 @@ class MigrateActorRunnable final : public Runnable {
} // namespace
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver, nsIEventTarget)
NS_IMPL_ISUPPORTS(RemoteLazyInputStreamThread, nsIObserver, nsIEventTarget)
/* static */
bool IPCBlobInputStreamThread::IsOnFileEventTarget(
bool RemoteLazyInputStreamThread::IsOnFileEventTarget(
nsIEventTarget* aEventTarget) {
MOZ_ASSERT(aEventTarget);
@ -86,42 +86,42 @@ bool IPCBlobInputStreamThread::IsOnFileEventTarget(
return true;
}
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
return gIPCBlobThread && aEventTarget == gIPCBlobThread->mThread;
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
return gRemoteLazyThread && aEventTarget == gRemoteLazyThread->mThread;
}
/* static */
IPCBlobInputStreamThread* IPCBlobInputStreamThread::Get() {
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
RemoteLazyInputStreamThread* RemoteLazyInputStreamThread::Get() {
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (gShutdownHasStarted) {
return nullptr;
}
return gIPCBlobThread;
return gRemoteLazyThread;
}
/* static */
IPCBlobInputStreamThread* IPCBlobInputStreamThread::GetOrCreate() {
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
RemoteLazyInputStreamThread* RemoteLazyInputStreamThread::GetOrCreate() {
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (gShutdownHasStarted) {
return nullptr;
}
if (!gIPCBlobThread) {
gIPCBlobThread = new IPCBlobInputStreamThread();
if (!gIPCBlobThread->Initialize()) {
if (!gRemoteLazyThread) {
gRemoteLazyThread = new RemoteLazyInputStreamThread();
if (!gRemoteLazyThread->Initialize()) {
return nullptr;
}
}
return gIPCBlobThread;
return gRemoteLazyThread;
}
bool IPCBlobInputStreamThread::Initialize() {
bool RemoteLazyInputStreamThread::Initialize() {
nsCOMPtr<nsIThread> thread;
nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
nsresult rv = NS_NewNamedThread("RemoteLzyStream", getter_AddRefs(thread));
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
@ -146,7 +146,7 @@ bool IPCBlobInputStreamThread::Initialize() {
return true;
}
void IPCBlobInputStreamThread::InitializeOnMainThread() {
void RemoteLazyInputStreamThread::InitializeOnMainThread() {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@ -162,11 +162,11 @@ void IPCBlobInputStreamThread::InitializeOnMainThread() {
}
NS_IMETHODIMP
IPCBlobInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
RemoteLazyInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (mThread) {
mThread->Shutdown();
@ -174,16 +174,16 @@ IPCBlobInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
}
gShutdownHasStarted = true;
gIPCBlobThread = nullptr;
gRemoteLazyThread = nullptr;
return NS_OK;
}
void IPCBlobInputStreamThread::MigrateActor(
void RemoteLazyInputStreamThread::MigrateActor(
RemoteLazyInputStreamChild* aActor) {
MOZ_ASSERT(aActor->State() == RemoteLazyInputStreamChild::eInactiveMigrating);
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (gShutdownHasStarted) {
return;
@ -198,7 +198,7 @@ void IPCBlobInputStreamThread::MigrateActor(
MigrateActorInternal(aActor);
}
void IPCBlobInputStreamThread::MigrateActorInternal(
void RemoteLazyInputStreamThread::MigrateActorInternal(
RemoteLazyInputStreamChild* aActor) {
RefPtr<Runnable> runnable = new MigrateActorRunnable(aActor);
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
@ -207,21 +207,21 @@ void IPCBlobInputStreamThread::MigrateActorInternal(
// nsIEventTarget
NS_IMETHODIMP_(bool)
IPCBlobInputStreamThread::IsOnCurrentThreadInfallible() {
RemoteLazyInputStreamThread::IsOnCurrentThreadInfallible() {
return mThread->IsOnCurrentThread();
}
NS_IMETHODIMP
IPCBlobInputStreamThread::IsOnCurrentThread(bool* aRetval) {
RemoteLazyInputStreamThread::IsOnCurrentThread(bool* aRetval) {
return mThread->IsOnCurrentThread(aRetval);
}
NS_IMETHODIMP
IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
uint32_t aFlags) {
RemoteLazyInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
uint32_t aFlags) {
nsCOMPtr<nsIRunnable> runnable(aRunnable);
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (gShutdownHasStarted) {
return NS_ERROR_NOT_INITIALIZED;
@ -231,25 +231,25 @@ IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
}
NS_IMETHODIMP
IPCBlobInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
uint32_t aFlags) {
RemoteLazyInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
uint32_t aFlags) {
nsCOMPtr<nsIRunnable> runnable(aRunnable);
return Dispatch(runnable.forget(), aFlags);
}
NS_IMETHODIMP
IPCBlobInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>,
uint32_t) {
RemoteLazyInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>,
uint32_t) {
return NS_ERROR_NOT_IMPLEMENTED;
}
bool IsOnDOMFileThread() {
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
MOZ_ASSERT(!gShutdownHasStarted);
MOZ_ASSERT(gIPCBlobThread);
MOZ_ASSERT(gRemoteLazyThread);
return gIPCBlobThread->IsOnCurrentThreadInfallible();
return gRemoteLazyThread->IsOnCurrentThreadInfallible();
}
void AssertIsOnDOMFileThread() { MOZ_ASSERT(IsOnDOMFileThread()); }

Просмотреть файл

@ -4,8 +4,8 @@
* 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_IPCBlobInputStreamThread_h
#define mozilla_dom_IPCBlobInputStreamThread_h
#ifndef mozilla_dom_RemoteLazyInputStreamThread_h
#define mozilla_dom_RemoteLazyInputStreamThread_h
#include "mozilla/dom/RemoteLazyInputStreamChild.h"
#include "nsIEventTarget.h"
@ -19,8 +19,8 @@ namespace dom {
class RemoteLazyInputStreamChild;
class IPCBlobInputStreamThread final : public nsIObserver,
public nsIEventTarget {
class RemoteLazyInputStreamThread final : public nsIObserver,
public nsIEventTarget {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
@ -28,9 +28,9 @@ class IPCBlobInputStreamThread final : public nsIObserver,
static bool IsOnFileEventTarget(nsIEventTarget* aEventTarget);
static IPCBlobInputStreamThread* Get();
static RemoteLazyInputStreamThread* Get();
static IPCBlobInputStreamThread* GetOrCreate();
static RemoteLazyInputStreamThread* GetOrCreate();
void MigrateActor(RemoteLazyInputStreamChild* aActor);
@ -39,7 +39,7 @@ class IPCBlobInputStreamThread final : public nsIObserver,
void InitializeOnMainThread();
private:
~IPCBlobInputStreamThread() = default;
~RemoteLazyInputStreamThread() = default;
void MigrateActorInternal(RemoteLazyInputStreamChild* aActor);
@ -57,4 +57,4 @@ void AssertIsOnDOMFileThread();
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_IPCBlobInputStreamThread_h
#endif // mozilla_dom_RemoteLazyInputStreamThread_h

Просмотреть файл

@ -29,11 +29,11 @@ UNIFIED_SOURCES += [
'FileCreatorChild.cpp',
'FileCreatorParent.cpp',
'IPCBlobInputStream.cpp',
'IPCBlobInputStreamThread.cpp',
'IPCBlobUtils.cpp',
'RemoteLazyInputStreamChild.cpp',
'RemoteLazyInputStreamParent.cpp',
'RemoteLazyInputStreamStorage.cpp',
'RemoteLazyInputStreamThread.cpp',
'TemporaryIPCBlobChild.cpp',
'TemporaryIPCBlobParent.cpp',
]

Просмотреть файл

@ -7,7 +7,6 @@
#include "LSObject.h"
#include "ActorsChild.h"
#include "IPCBlobInputStreamThread.h"
#include "LocalStorageCommon.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/StaticPrefs_dom.h"
@ -19,6 +18,7 @@
#include "nsContentUtils.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsThread.h"
#include "RemoteLazyInputStreamThread.h"
/**
* Automatically cancel and abort synchronous LocalStorage requests (for example
@ -83,15 +83,16 @@ class NestedEventTargetWrapper final : public nsISerialEventTarget {
* The normal life-cycle of this method looks like:
* - Main Thread: LSObject::DoRequestSynchronously creates a RequestHelper and
* invokes StartAndReturnResponse(). It pushes the event queue and Dispatches
* the RequestHelper to the DOM File Thread.
* - DOM File Thread: RequestHelper::Run is called, invoking Start() which
* invokes LSObject::StartRequest, which gets-or-creates the PBackground actor
* if necessary (which may dispatch a runnable to the nested event queue on
* the main thread), sends LSRequest constructor which is provided with a
* callback reference to the RequestHelper. State advances to ResponsePending.
* - DOM File Thread:: LSRequestChild::Recv__delete__ is received, which invokes
* RequestHelepr::OnResponse, advancing the state to Finishing and dispatching
* RequestHelper to its own nested event target.
* the RequestHelper to the RemoteLazyInputStream thread.
* - RemoteLazyInputStream Thread: RequestHelper::Run is called, invoking
* Start() which invokes LSObject::StartRequest, which gets-or-creates the
* PBackground actor if necessary (which may dispatch a runnable to the nested
* event queue on the main thread), sends LSRequest constructor which is
* provided with a callback reference to the RequestHelper. State advances to
* ResponsePending.
* - RemoteLazyInputStreamThread: LSRequestChild::Recv__delete__ is received,
* which invokes RequestHelepr::OnResponse, advancing the state to Finishing
* and dispatching RequestHelper to its own nested event target.
* - Main Thread: RequestHelper::Run is called, invoking Finish() which advances
* the state to Complete and sets mWaiting to false, allowing the nested event
* loop being spun by StartAndReturnResponse to cease spinning and return the
@ -103,11 +104,12 @@ class NestedEventTargetWrapper final : public nsISerialEventTarget {
class RequestHelper final : public Runnable, public LSRequestChildCallback {
enum class State {
/**
* The RequestHelper has been created and dispatched to the DOM File Thread.
* The RequestHelper has been created and dispatched to the
* RemoteLazyInputStream Thread.
*/
Initial,
/**
* Start() has been invoked on the DOM File Thread and
* Start() has been invoked on the RemoteLazyInputStream Thread and
* LSObject::StartRequest has been invoked from there, sending an IPC
* message to PBackground to service the request. We stay in this state
* until a response is received.
@ -217,7 +219,7 @@ void LSObject::Initialize() {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIEventTarget> domFileThread =
IPCBlobInputStreamThread::GetOrCreate();
RemoteLazyInputStreamThread::GetOrCreate();
if (NS_WARN_IF(!domFileThread)) {
return;
}
@ -827,9 +829,9 @@ nsresult LSObject::DoRequestSynchronously(const LSRequestParams& aParams,
RefPtr<RequestHelper> helper = new RequestHelper(this, aParams);
// This will start and finish the request on the DOM File thread.
// This will start and finish the request on the RemoteLazyInputStream thread.
// The owning thread is synchronously blocked while the request is
// asynchronously processed on the DOM File thread.
// asynchronously processed on the RemoteLazyInputStream thread.
nsresult rv = helper->StartAndReturnResponse(aResponse);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@ -896,7 +898,7 @@ nsresult LSObject::EnsureDatabase() {
uint64_t datastoreId = prepareDatastoreResponse.datastoreId();
// The datastore is now ready on the parent side (prepared by the asynchronous
// request on the DOM File thread).
// request on the RemoteLazyInputStream thread).
// Let's create a direct connection to the datastore (through a database
// actor) from the owning thread.
// Note that we now can't error out, otherwise parent will keep an extra
@ -961,7 +963,7 @@ nsresult LSObject::EnsureObserver() {
uint64_t observerId = prepareObserverResponse.observerId();
// The obsserver is now ready on the parent side (prepared by the asynchronous
// request on the DOM File thread).
// request on the RemoteLazyInputStream thread).
// Let's create a direct connection to the observer (through an observer
// actor) from the owning thread.
// Note that we now can't error out, otherwise parent will keep an extra
@ -1105,8 +1107,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
// Normally, we would use the standard way of blocking the thread using
// a monitor.
// The problem is that BackgroundChild::GetOrCreateForCurrentThread()
// called on the DOM File thread may dispatch a runnable to the main
// thread to finish initialization of PBackground. A monitor would block
// called on the RemoteLazyInputStream thread may dispatch a runnable to the
// main thread to finish initialization of PBackground. A monitor would block
// the main thread and the runnable would never get executed causing the
// helper to be stuck in a wait loop.
// However, BackgroundChild::GetOrCreateForCurrentThread() supports passing
@ -1127,8 +1129,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
new NestedEventTargetWrapper(mNestedEventTarget);
nsCOMPtr<nsIEventTarget> domFileThread =
XRE_IsParentProcess() ? IPCBlobInputStreamThread::GetOrCreate()
: IPCBlobInputStreamThread::Get();
XRE_IsParentProcess() ? RemoteLazyInputStreamThread::GetOrCreate()
: RemoteLazyInputStreamThread::Get();
if (NS_WARN_IF(!domFileThread)) {
return NS_ERROR_FAILURE;
}
@ -1202,8 +1204,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
// We can check mWaiting here because it's only ever touched on the main
// thread.
if (NS_WARN_IF(mWaiting)) {
// Don't touch mResponse, mResultCode or mState here! The DOM File Thread
// may be accessing them at the same moment.
// Don't touch mResponse, mResultCode or mState here! The
// RemoteLazyInputStream Thread may be accessing them at the same moment.
RefPtr<RequestHelper> self = this;

Просмотреть файл

@ -81,16 +81,16 @@
* like directory locking before sending a reply to a synchronous message, then
* we would have to block the thread or spin the event loop which is usually a
* bad idea, especially in the main process.
* Instead, we can use a special thread in the content process called DOM File
* thread for communication with the main process using asynchronous messages
* and synchronously block the main thread until the DOM File thread is done
* (the main thread blocking is a bit more complicated, see the comment in
* RequestHelper::StartAndReturnResponse for more details).
* Anyway, the extra hop to the DOM File thread brings another overhead and
* latency. The final solution is to use a combination of the special thread
* for complex stuff like datastore preparation and synchronous IPC messages
* sent directly from the main thread for database access when data is already
* loaded from disk into memory.
* Instead, we can use a special thread in the content process called
* RemoteLazyInputStream thread for communication with the main process using
* asynchronous messages and synchronously block the main thread until the DOM
* File thread is done (the main thread blocking is a bit more complicated, see
* the comment in RequestHelper::StartAndReturnResponse for more details).
* Anyway, the extra hop to the RemoteLazyInputStream thread brings another
* overhead and latency. The final solution is to use a combination of the
* special thread for complex stuff like datastore preparation and synchronous
* IPC messages sent directly from the main thread for database access when data
* is already loaded from disk into memory.
*
* Requests
* ~~~~~~~~
@ -116,13 +116,13 @@
* responses and do safe main thread blocking at the same time.
* It inherits from the "Runnable" class, so instances are ref counted and
* they are internally used on multiple threads (specifically on the main
* thread and on the DOM File thread). Anyway, users should create and use
* instances of this class only on the main thread (apart from a special case
* when we need to cancel the request from an internal chromium IPC thread to
* prevent a dead lock involving CPOWs).
* thread and on the RemoteLazyInputStream thread). Anyway, users should create
* and use instances of this class only on the main thread (apart from a special
* case when we need to cancel the request from an internal chromium IPC thread
* to prevent a dead lock involving CPOWs).
* The actual child actor is represented by the "LSRequestChild" class that
* implements the "PBackgroundLSRequestChild" interface. An "LSRequestChild"
* instance is not ref counted and lives on the DOM File thread.
* instance is not ref counted and lives on the RemoteLazyInputStream thread.
* Request responses are passed using the "LSRequestChildCallback" interface.
*
* Preparation of a datastore
@ -157,9 +157,10 @@
* In theory, the datastore preparation request could return a database actor
* directly (instead of returning an id intended for database linking to a
* datastore). However, as it was explained above, the preparation must be done
* on the DOM File thread and database objects are used on the main thread. The
* returned actor would have to be migrated from the DOM File thread to the
* main thread and that's something which our IPDL doesn't support yet.
* on the RemoteLazyInputStream thread and database objects are used on the main
* thread. The returned actor would have to be migrated from the
* RemoteLazyInputStream thread to the main thread and that's something which
* our IPDL doesn't support yet.
*
* Exposing local storage
* ~~~~~~~~~~~~~~~~~~~~~~

Просмотреть файл

@ -19,12 +19,12 @@ class AsyncRequestHelper final : public Runnable,
public LSRequestChildCallback {
enum class State {
/**
* The AsyncRequestHelper has been created and dispatched to the DOM File
* Thread.
* The AsyncRequestHelper has been created and dispatched to the
* RemoteLazyInputStream Thread.
*/
Initial,
/**
* Start() has been invoked on the DOM File Thread and
* Start() has been invoked on the RemoteLazyInputStream Thread and
* LocalStorageManager2::StartRequest has been invoked from there, sending
* an IPC message to PBackground to service the request. We stay in this
* state until a response is received.
@ -300,9 +300,10 @@ LocalStorageManager2::Preload(nsIPrincipal* aPrincipal, JSContext* aContext,
RefPtr<AsyncRequestHelper> helper =
new AsyncRequestHelper(this, promise, params);
// This will start and finish the async request on the DOM File thread.
// This must be done on DOM File Thread because it's very likely that a
// content process will issue a prepare datastore request for the same
// This will start and finish the async request on the RemoteLazyInputStream
// thread.
// This must be done on RemoteLazyInputStream Thread because it's very likely
// that a content process will issue a prepare datastore request for the same
// principal while blocking the content process on the main thread.
// There would be a potential for deadlock if the preloading was initialized
// from the main thread of the parent process and a11y issued a synchronous
@ -406,7 +407,7 @@ nsresult AsyncRequestHelper::Dispatch() {
AssertIsOnOwningThread();
nsCOMPtr<nsIEventTarget> domFileThread =
IPCBlobInputStreamThread::GetOrCreate();
RemoteLazyInputStreamThread::GetOrCreate();
if (NS_WARN_IF(!domFileThread)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -93,7 +93,8 @@ child:
* Cancel() would be received by the parent after it had already sent
* __delete__. (Which may no longer be fatal thanks to improvements to the
* IPC layer, but it would still lead to warnings, etc. And we don't
* expect PBackground to be highly contended nor the DOM File thread.)
* expect PBackground to be highly contended nor the RemoteLazyInputStream
* thread.)
*/
async Ready();
};