Bug 1613873 - P4: Use nsInputStreamPump off main thread completely r=dragana

Differential Revision: https://phabricator.services.mozilla.com/D62919

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kershaw Chang 2020-03-02 12:40:06 +00:00
Родитель 69329b4fc3
Коммит e2cd8195a0
2 изменённых файлов: 29 добавлений и 6 удалений

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

@ -49,6 +49,7 @@ nsInputStreamPump::nsInputStreamPump()
mCloseWhenDone(false), mCloseWhenDone(false),
mRetargeting(false), mRetargeting(false),
mAsyncStreamIsBuffered(false), mAsyncStreamIsBuffered(false),
mOffMainThread(!NS_IsMainThread()),
mMutex("nsInputStreamPump") {} mMutex("nsInputStreamPump") {}
nsresult nsInputStreamPump::Create(nsInputStreamPump** result, nsresult nsInputStreamPump::Create(nsInputStreamPump** result,
@ -112,8 +113,9 @@ nsresult nsInputStreamPump::EnsureWaiting() {
// on only one thread at a time. // on only one thread at a time.
MOZ_ASSERT(mAsyncStream); MOZ_ASSERT(mAsyncStream);
if (!mWaitingForInputStreamReady && !mProcessingCallbacks) { if (!mWaitingForInputStreamReady && !mProcessingCallbacks) {
// Ensure OnStateStop is called on the main thread. // Ensure OnStateStop is called on the main thread only when this pump is
if (mState == STATE_STOP) { // created on main thread.
if (mState == STATE_STOP && !mOffMainThread) {
nsCOMPtr<nsIEventTarget> mainThread = nsCOMPtr<nsIEventTarget> mainThread =
mLabeledMainThreadTarget ? mLabeledMainThreadTarget mLabeledMainThreadTarget ? mLabeledMainThreadTarget
: do_AddRef(GetMainThreadEventTarget()); : do_AddRef(GetMainThreadEventTarget());
@ -183,7 +185,13 @@ nsInputStreamPump::GetStatus(nsresult* status) {
NS_IMETHODIMP NS_IMETHODIMP
nsInputStreamPump::Cancel(nsresult status) { nsInputStreamPump::Cancel(nsresult status) {
MOZ_ASSERT(NS_IsMainThread()); #if DEBUG
if (mOffMainThread) {
MOZ_ASSERT_IF(mTargetThread, mTargetThread->IsOnCurrentThread());
} else {
MOZ_ASSERT(NS_IsMainThread());
}
#endif
RecursiveMutexAutoLock lock(mMutex); RecursiveMutexAutoLock lock(mMutex);
@ -292,6 +300,12 @@ nsInputStreamPump::Init(nsIInputStream* stream, uint32_t segsize,
mSegCount = segcount; mSegCount = segcount;
mCloseWhenDone = closeWhenDone; mCloseWhenDone = closeWhenDone;
mLabeledMainThreadTarget = mainThreadTarget; mLabeledMainThreadTarget = mainThreadTarget;
if (mOffMainThread && mLabeledMainThreadTarget) {
MOZ_ASSERT(
false,
"Init stream pump off main thread with a main thread event target.");
return NS_ERROR_FAILURE;
}
return NS_OK; return NS_OK;
} }
@ -302,7 +316,7 @@ nsInputStreamPump::AsyncRead(nsIStreamListener* listener, nsISupports* ctxt) {
NS_ENSURE_TRUE(mState == STATE_IDLE, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(mState == STATE_IDLE, NS_ERROR_IN_PROGRESS);
NS_ENSURE_ARG_POINTER(listener); NS_ENSURE_ARG_POINTER(listener);
MOZ_ASSERT(NS_IsMainThread(), MOZ_ASSERT(NS_IsMainThread() || mOffMainThread,
"nsInputStreamPump should be read from the " "nsInputStreamPump should be read from the "
"main thread only."); "main thread only.");
@ -441,7 +455,7 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream* stream) {
// Set mRetargeting so EnsureWaiting will be called. It ensures that // Set mRetargeting so EnsureWaiting will be called. It ensures that
// OnStateStop is called on the main thread. // OnStateStop is called on the main thread.
if (nextState == STATE_STOP && !NS_IsMainThread()) { if (nextState == STATE_STOP && !NS_IsMainThread() && !mOffMainThread) {
mRetargeting = true; mRetargeting = true;
} }
@ -631,7 +645,7 @@ nsresult nsInputStreamPump::CallOnStateStop() {
uint32_t nsInputStreamPump::OnStateStop() { uint32_t nsInputStreamPump::OnStateStop() {
mMutex.AssertCurrentThreadIn(); mMutex.AssertCurrentThreadIn();
if (!NS_IsMainThread()) { if (!NS_IsMainThread() && !mOffMainThread) {
// This method can be called on a different thread if nsInputStreamPump // This method can be called on a different thread if nsInputStreamPump
// is used off the main-thread. // is used off the main-thread.
nsresult rv = mLabeledMainThreadTarget->Dispatch( nsresult rv = mLabeledMainThreadTarget->Dispatch(
@ -726,6 +740,12 @@ nsInputStreamPump::RetargetDeliveryTo(nsIEventTarget* aNewTarget) {
return NS_OK; return NS_OK;
} }
if (mOffMainThread) {
// Don't support retargeting if this pump is already used off the main
// thread.
return NS_ERROR_FAILURE;
}
// Ensure that |mListener| and any subsequent listeners can be retargeted // Ensure that |mListener| and any subsequent listeners can be retargeted
// to another thread. // to another thread.
nsresult rv = NS_OK; nsresult rv = NS_OK;

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

@ -98,6 +98,9 @@ class nsInputStreamPump final : public nsIInputStreamPump,
bool mCloseWhenDone; bool mCloseWhenDone;
bool mRetargeting; bool mRetargeting;
bool mAsyncStreamIsBuffered; bool mAsyncStreamIsBuffered;
// Indicate whether nsInputStreamPump is used completely off main thread.
// If true, OnStateStop() is executed off main thread.
bool mOffMainThread;
// Protects state/member var accesses across multiple threads. // Protects state/member var accesses across multiple threads.
mozilla::RecursiveMutex mMutex; mozilla::RecursiveMutex mMutex;
}; };