mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1186745 part 1 - Add LeakRefPtr for pointer leaking by default. r=froydnj
This class can be used instead of raw pointer for a sound leaking-by-default behavior. Also it could take advantage of move semantic check in the future. --HG-- extra : source : 47cd2c22bafc8d4bb1c7e1dce3b45517aaec199f
This commit is contained in:
parent
ee2cd3bbc3
commit
4dad63f727
@ -106,6 +106,7 @@ if CONFIG['_MSC_VER']:
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../build',
|
||||
'../threads',
|
||||
]
|
||||
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "LeakRefPtr.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
# include "nsThreadManager.h"
|
||||
@ -27,6 +28,8 @@ using mozilla::IsVistaOrLater;
|
||||
#include <pratom.h>
|
||||
#include <prthread.h>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#ifndef XPCOM_GLUE_AVOID_NSPR
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsRunnable, nsIRunnable)
|
||||
@ -164,17 +167,16 @@ NS_DispatchToCurrentThread(nsIRunnable* aEvent)
|
||||
NS_METHOD
|
||||
NS_DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDispatchFlags)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event(aEvent);
|
||||
LeakRefPtr<nsIRunnable> event(Move(aEvent));
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
NS_ASSERTION(false, "Failed NS_DispatchToMainThread() in shutdown; leaking");
|
||||
// NOTE: if you stop leaking here, adjust Promise::MaybeReportRejected(),
|
||||
// which assumes a leak here, or split into leaks and no-leaks versions
|
||||
nsIRunnable* temp = event.forget().take(); // leak without using "unused <<" due to Windows (boo)
|
||||
return temp ? rv : rv; // to make compiler not bletch on us
|
||||
return rv;
|
||||
}
|
||||
return thread->Dispatch(event.forget(), aDispatchFlags);
|
||||
return thread->Dispatch(event.take(), aDispatchFlags);
|
||||
}
|
||||
|
||||
// In the case of failure with a newly allocated runnable with a
|
||||
|
@ -38,6 +38,7 @@ DEFINES['XPCOM_GLUE'] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../build',
|
||||
'../../threads',
|
||||
]
|
||||
|
||||
# Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc
|
||||
|
@ -30,6 +30,7 @@ DEFINES['XPCOM_GLUE'] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../../build',
|
||||
'../../../threads',
|
||||
]
|
||||
|
||||
# Statically link to the CRT on Windows
|
||||
|
@ -28,6 +28,7 @@ if CONFIG['_MSC_VER']:
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../build',
|
||||
'../../threads',
|
||||
]
|
||||
|
||||
# Statically link to the CRT on Windows
|
||||
|
48
xpcom/threads/LeakRefPtr.h
Normal file
48
xpcom/threads/LeakRefPtr.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/* Smart pointer which leaks its owning refcounted object by default. */
|
||||
|
||||
#ifndef LeakRefPtr_h
|
||||
#define LeakRefPtr_h
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Instance of this class behaves like a raw pointer which leaks the
|
||||
* resource it's owning if not explicitly released.
|
||||
*/
|
||||
template<class T>
|
||||
class LeakRefPtr
|
||||
{
|
||||
public:
|
||||
explicit LeakRefPtr(already_AddRefed<T>&& aPtr)
|
||||
: mRawPtr(aPtr.take()) { }
|
||||
|
||||
explicit operator bool() const { return !!mRawPtr; }
|
||||
|
||||
LeakRefPtr<T>& operator=(already_AddRefed<T>&& aPtr)
|
||||
{
|
||||
mRawPtr = aPtr.take();
|
||||
return *this;
|
||||
}
|
||||
|
||||
already_AddRefed<T> take()
|
||||
{
|
||||
T* rawPtr = mRawPtr;
|
||||
mRawPtr = nullptr;
|
||||
return already_AddRefed<T>(rawPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
T* MOZ_OWNING_REF mRawPtr;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // LeakRefPtr_h
|
@ -36,6 +36,7 @@
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "LeakRefPtr.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -541,6 +542,9 @@ nsThread::PutEvent(nsIRunnable* aEvent, nsNestedEventTarget* aTarget)
|
||||
nsresult
|
||||
nsThread::PutEvent(already_AddRefed<nsIRunnable>&& aEvent, nsNestedEventTarget* aTarget)
|
||||
{
|
||||
// We want to leak the reference when we fail to dispatch it, so that
|
||||
// we won't release the event in a wrong thread.
|
||||
LeakRefPtr<nsIRunnable> event(Move(aEvent));
|
||||
nsCOMPtr<nsIThreadObserver> obs;
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
@ -554,11 +558,9 @@ nsThread::PutEvent(already_AddRefed<nsIRunnable>&& aEvent, nsNestedEventTarget*
|
||||
nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot;
|
||||
if (!queue || (queue == &mEventsRoot && mEventsAreDoomed)) {
|
||||
NS_WARNING("An event was posted to a thread that will never run it (rejected)");
|
||||
nsCOMPtr<nsIRunnable> temp(aEvent);
|
||||
nsIRunnable* temp2 = temp.forget().take(); // can't use unused << aEvent here due to Windows (boo)
|
||||
return temp2 ? NS_ERROR_UNEXPECTED : NS_ERROR_UNEXPECTED; // to make compiler not bletch on us
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
queue->PutEvent(Move(aEvent), lock);
|
||||
queue->PutEvent(event.take(), lock);
|
||||
|
||||
// Make sure to grab the observer before dropping the lock, otherwise the
|
||||
// event that we just placed into the queue could run and eventually delete
|
||||
|
Loading…
Reference in New Issue
Block a user