Bug 1241518 - Part 4: Switch nsThread to use UniquePtr r=KrisWright,kmag

This switches over one usage of `nsAutoPtr` that was just used to scope an allocation, a stack variable is used instead. The shutdown contexts array is switched over to hold `UniquePtr`s which required adding a helper to find elements in the array as `UniquePtr` does not auto-convert to its pointer type.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eric Rahm 2020-01-07 00:06:08 +00:00
parent bf24e992e3
commit 3c0275f1d5
3 changed files with 28 additions and 15 deletions

View File

@ -18,7 +18,6 @@
#include "nsMemoryPressure.h"
#include "nsThreadManager.h"
#include "nsIClassInfoImpl.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsQueryObject.h"
#include "pratom.h"
@ -258,6 +257,12 @@ struct nsThreadShutdownContext {
bool mIsMainThreadJoining;
};
bool nsThread::ShutdownContextsComp::Equals(
const ShutdownContexts::elem_type& a,
const ShutdownContexts::elem_type::Pointer b) const {
return a.get() == b;
}
// This event is responsible for notifying nsThread::Shutdown that it is time
// to call PR_JoinThread. It implements nsICancelableRunnable so that it can
// run on a DOM Worker thread (where all events must implement
@ -452,11 +457,10 @@ void nsThread::ThreadFunc(void* aArg) {
{
// Scope for MessageLoop.
nsAutoPtr<MessageLoop> loop(
new MessageLoop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD, self));
MessageLoop loop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD, self);
// Now, process incoming events...
loop->Run();
loop.Run();
BackgroundChild::CloseForCurrentThread();
@ -653,7 +657,7 @@ nsThread::~nsThread() {
// requesting shutdown on another, which can be helpful for diagnosing
// the leak.
for (size_t i = 0; i < mRequestedShutdownContexts.Length(); ++i) {
Unused << mRequestedShutdownContexts[i].forget();
Unused << mRequestedShutdownContexts[i].release();
}
#endif
}
@ -843,15 +847,15 @@ nsThreadShutdownContext* nsThread::ShutdownInternal(bool aSync) {
MOZ_DIAGNOSTIC_ASSERT(currentThread->EventQueue(),
"Shutdown() may only be called from an XPCOM thread");
nsAutoPtr<nsThreadShutdownContext>& context =
*currentThread->mRequestedShutdownContexts.AppendElement();
context =
// Allocate a shutdown context and store a strong ref.
auto context =
new nsThreadShutdownContext(WrapNotNull(this), currentThread, aSync);
Unused << *currentThread->mRequestedShutdownContexts.EmplaceBack(context);
// Set mShutdownContext and wake up the thread in case it is waiting for
// events to process.
nsCOMPtr<nsIRunnable> event =
new nsThreadShutdownEvent(WrapNotNull(this), WrapNotNull(context.get()));
new nsThreadShutdownEvent(WrapNotNull(this), WrapNotNull(context));
// XXXroc What if posting the event fails due to OOM?
mEvents->PutEvent(event.forget(), EventQueuePriority::Normal);
@ -887,7 +891,8 @@ void nsThread::ShutdownComplete(NotNull<nsThreadShutdownContext*> aContext) {
// Delete aContext.
// aContext might not be in mRequestedShutdownContexts if it belongs to a
// thread that was leaked by calling nsIThreadPool::ShutdownWithTimeout.
aContext->mJoiningThread->mRequestedShutdownContexts.RemoveElement(aContext);
aContext->mJoiningThread->mRequestedShutdownContexts.RemoveElement(
aContext, ShutdownContextsComp{});
}
void nsThread::WaitForAllAsynchronousShutdowns() {

View File

@ -20,7 +20,6 @@
#include "mozilla/SynchronizedEventQueue.h"
#include "mozilla/NotNull.h"
#include "mozilla/TimeStamp.h"
#include "nsAutoPtr.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Array.h"
@ -207,7 +206,15 @@ class nsThread : public nsIThreadInternal,
RefPtr<mozilla::ThreadEventTarget> mEventTarget;
// The shutdown contexts for any other threads we've asked to shut down.
using ShutdownContexts = nsTArray<nsAutoPtr<struct nsThreadShutdownContext>>;
using ShutdownContexts =
nsTArray<mozilla::UniquePtr<struct nsThreadShutdownContext>>;
// Helper for finding a ShutdownContext in the contexts array.
struct ShutdownContextsComp {
bool Equals(const ShutdownContexts::elem_type& a,
const ShutdownContexts::elem_type::Pointer b) const;
};
ShutdownContexts mRequestedShutdownContexts;
// The shutdown context for ourselves.
struct nsThreadShutdownContext* mShutdownContext;

View File

@ -473,17 +473,18 @@ nsThreadPool::ShutdownWithTimeout(int32_t aTimeoutMs) {
// For any threads that have not shutdown yet, we need to remove them from
// mRequestedShutdownContexts so the thread manager does not wait for them
// at shutdown.
static const nsThread::ShutdownContextsComp comparator{};
for (int32_t i = 0; i < threads.Count(); ++i) {
nsThread* thread = static_cast<nsThread*>(threads[i]);
// If mThread is not null on the thread it means that it hasn't shutdown
// context[i] corresponds to thread[i]
if (thread->mThread && contexts[i]) {
auto index =
currentThread->mRequestedShutdownContexts.IndexOf(contexts[i]);
auto index = currentThread->mRequestedShutdownContexts.IndexOf(
contexts[i], 0, comparator);
if (index != nsThread::ShutdownContexts::NoIndex) {
// We must leak the shutdown context just in case the leaked thread
// does get unstuck and completes before the main thread is done.
currentThread->mRequestedShutdownContexts[index].forget();
Unused << currentThread->mRequestedShutdownContexts[index].release();
currentThread->mRequestedShutdownContexts.RemoveElementsAt(index, 1);
}
}