Bug 1074557 - Remove the lock in nsWindowMediator. r=Neil

This commit is contained in:
Brian Marshall 2014-10-16 15:45:17 -07:00
parent bc4244f5a9
commit 08a6fc02ef
2 changed files with 21 additions and 34 deletions

View File

@ -53,8 +53,7 @@ nsWindowMediator::GetDOMWindow(nsIXULWindow* inWindow,
nsWindowMediator::nsWindowMediator() :
mEnumeratorList(), mOldestWindow(nullptr), mTopmostWindow(nullptr),
mTimeStamp(0), mSortingZOrder(false), mReady(false),
mListLock("nsWindowMediator.mListLock")
mTimeStamp(0), mSortingZOrder(false), mReady(false)
{
}
@ -79,6 +78,7 @@ nsresult nsWindowMediator::Init()
NS_IMETHODIMP nsWindowMediator::RegisterWindow(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
if (GetInfoFor(inWindow)) {
@ -96,7 +96,6 @@ NS_IMETHODIMP nsWindowMediator::RegisterWindow(nsIXULWindow* inWindow)
WindowTitleData winData = { inWindow, nullptr };
mListeners.EnumerateForwards(notifyOpenWindow, &winData);
MutexAutoLock lock(mListLock);
if (mOldestWindow)
windowInfo->InsertAfter(mOldestWindow->mOlder, nullptr);
else
@ -108,8 +107,8 @@ NS_IMETHODIMP nsWindowMediator::RegisterWindow(nsIXULWindow* inWindow)
NS_IMETHODIMP
nsWindowMediator::UnregisterWindow(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsWindowInfo *info = GetInfoFor(inWindow);
if (info)
return UnregisterWindow(info);
@ -192,9 +191,10 @@ nsWindowMediator::GetInfoFor(nsIWidget *aWindow)
NS_IMETHODIMP
nsWindowMediator::GetEnumerator(const char16_t* inType, nsISimpleEnumerator** outEnumerator)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outEnumerator);
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsAppShellWindowEnumerator *enumerator = new nsASDOMWindowEarlyToLateEnumerator(inType, *this);
if (enumerator)
return enumerator->QueryInterface(NS_GET_IID(nsISimpleEnumerator) , (void**)outEnumerator);
@ -205,9 +205,10 @@ nsWindowMediator::GetEnumerator(const char16_t* inType, nsISimpleEnumerator** ou
NS_IMETHODIMP
nsWindowMediator::GetXULWindowEnumerator(const char16_t* inType, nsISimpleEnumerator** outEnumerator)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outEnumerator);
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsAppShellWindowEnumerator *enumerator = new nsASXULWindowEarlyToLateEnumerator(inType, *this);
if (enumerator)
return enumerator->QueryInterface(NS_GET_IID(nsISimpleEnumerator) , (void**)outEnumerator);
@ -220,9 +221,10 @@ nsWindowMediator::GetZOrderDOMWindowEnumerator(
const char16_t *aWindowType, bool aFrontToBack,
nsISimpleEnumerator **_retval)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsAppShellWindowEnumerator *enumerator;
if (aFrontToBack)
enumerator = new nsASDOMWindowFrontToBackEnumerator(aWindowType, *this);
@ -239,9 +241,10 @@ nsWindowMediator::GetZOrderXULWindowEnumerator(
const char16_t *aWindowType, bool aFrontToBack,
nsISimpleEnumerator **_retval)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsAppShellWindowEnumerator *enumerator;
if (aFrontToBack)
enumerator = new nsASXULWindowFrontToBackEnumerator(aWindowType, *this);
@ -270,6 +273,7 @@ nsWindowMediator::RemoveEnumerator(nsAppShellWindowEnumerator * inEnumerator)
NS_IMETHODIMP
nsWindowMediator::GetMostRecentWindow(const char16_t* inType, nsIDOMWindow** outWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outWindow);
*outWindow = nullptr;
if (!mReady)
@ -277,10 +281,7 @@ nsWindowMediator::GetMostRecentWindow(const char16_t* inType, nsIDOMWindow** out
// Find the most window with the highest time stamp that matches
// the requested type
MutexAutoLock lock(mListLock);
nsWindowInfo *info = MostRecentWindowInfo(inType);
if (info && info->mWindow) {
nsCOMPtr<nsIDOMWindow> DOMWindow;
if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {
@ -356,8 +357,8 @@ nsWindowMediator::GetCurrentInnerWindowWithId(uint64_t aWindowID,
NS_IMETHODIMP
nsWindowMediator::UpdateWindowTimeStamp(nsIXULWindow* inWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsWindowInfo *info = GetInfoFor(inWindow);
if (info) {
// increment the window's time stamp
@ -371,8 +372,8 @@ NS_IMETHODIMP
nsWindowMediator::UpdateWindowTitle(nsIXULWindow* inWindow,
const char16_t* inTitle)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
if (GetInfoFor(inWindow)) {
WindowTitleData winData = { inWindow, inTitle };
mListeners.EnumerateForwards(notifyWindowTitleChange, &winData);
@ -396,6 +397,7 @@ nsWindowMediator::CalculateZPosition(
nsIWidget **outBelow,
bool *outAltered)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(outBelow);
NS_ENSURE_STATE(mReady);
@ -426,8 +428,6 @@ nsWindowMediator::CalculateZPosition(
uint32_t inZ;
GetZLevel(inWindow, &inZ);
MutexAutoLock lock(mListLock);
if (inPosition == nsIWindowMediator::zLevelBelow) {
// locate inBelow. use topmost if it can't be found or isn't in the
// z-order list
@ -526,6 +526,7 @@ nsWindowMediator::SetZPosition(
uint32_t inPosition,
nsIXULWindow *inBelow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
nsWindowInfo *inInfo,
*belowInfo;
@ -540,7 +541,6 @@ nsWindowMediator::SetZPosition(
return NS_OK;
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
/* Locate inWindow and unlink it from the z-order list.
It's important we look for it in the age list, not the z-order list.
@ -597,8 +597,8 @@ nsWindowMediator::GetZLevel(nsIXULWindow *aWindow, uint32_t *_retval)
NS_IMETHODIMP
nsWindowMediator::SetZLevel(nsIXULWindow *aWindow, uint32_t aZLevel)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_STATE(mReady);
MutexAutoLock lock(mListLock);
nsWindowInfo *info = GetInfoFor(aWindow);
NS_ASSERTION(info, "setting z level of unregistered window");
@ -622,7 +622,7 @@ nsWindowMediator::SetZLevel(nsIXULWindow *aWindow, uint32_t aZLevel)
has been changed, so one window is potentially out of place. Such a sort
is most efficiently done in a particular direction. Use this one
if a window's z level has just been reduced, so the sort is most efficiently
done front to back. Assumes caller has locked mListLock.
done front to back.
Note it's hardly worth going to all the trouble to write two versions
of this method except that if we choose the inefficient sorting direction,
on slow systems windows could visibly bubble around the window that
@ -777,19 +777,9 @@ nsWindowMediator::Observe(nsISupports* aSubject,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown") && mReady) {
// Unregistering a window may cause its destructor to run, causing it to
// call into the window mediator, try to acquire mListLock, and deadlock.
// Our solution is to hold strong refs to all windows until we release
// mListLock.
nsTArray<nsCOMPtr<nsIXULWindow> > windows;
{
MutexAutoLock lock(mListLock);
while (mOldestWindow) {
windows.AppendElement(mOldestWindow->mWindow);
UnregisterWindow(mOldestWindow);
}
}
MOZ_RELEASE_ASSERT(NS_IsMainThread());
while (mOldestWindow)
UnregisterWindow(mOldestWindow);
mReady = false;
}
return NS_OK;

View File

@ -6,7 +6,6 @@
#ifndef nsWindowMediator_h_
#define nsWindowMediator_h_
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsIWindowMediator.h"
#include "nsIObserver.h"
@ -24,7 +23,6 @@ class nsASDOMWindowBackToFrontEnumerator;
class nsASXULWindowBackToFrontEnumerator;
class nsIWindowMediatorListener;
struct nsWindowInfo;
struct PRLock;
class nsWindowMediator :
public nsIWindowMediator,
@ -71,7 +69,6 @@ private:
int32_t mTimeStamp;
bool mSortingZOrder;
bool mReady;
mozilla::Mutex mListLock;
nsCOMArray<nsIWindowMediatorListener> mListeners;
};