author | Randell Jesup <rjesup@jesup.org> |
Mon, 21 May 2018 15:30:35 -0400 | |
changeset 419253 | a314710b0acd38afc7de74f0306f514b50d84463 |
parent 419252 | 4d511f7fc5b5c16fdfea91242dea6086cd57c8c3 |
child 419254 | 603804d62ce82bbb6fe906bcf928eb8e7b8ae9aa |
push id | 34032 |
push user | nbeleuzu@mozilla.com |
push date | Tue, 22 May 2018 09:50:22 +0000 |
treeherder | mozilla-central@f85be0c4f056 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froyd |
bugs | 1425930 |
milestone | 62.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/xpcom/ds/Observer.h +++ b/xpcom/ds/Observer.h @@ -52,32 +52,52 @@ public: } /** * Remove the observer from the observer list. * @return Whether the observer has been found in the list. */ bool RemoveObserver(Observer<T>* aObserver) { - return mObservers.RemoveElement(aObserver); + if (mObservers.RemoveElement(aObserver)) { + if (!mBroadcastCopy.IsEmpty()) { + // Annoyingly, someone could RemoveObserver() an item on the list + // while we're in a Broadcast()'s Notify() call. + auto i = mBroadcastCopy.IndexOf(aObserver); + MOZ_ASSERT(i != mBroadcastCopy.NoIndex); + mBroadcastCopy[i] = nullptr; + } + return true; + } + return false; } uint32_t Length() { return mObservers.Length(); } + /** + * Call Notify() on each item in the list. + * Handles the case of Notify() calling RemoveObserver() + */ void Broadcast(const T& aParam) { - nsTArray<Observer<T>*> observersCopy(mObservers); - uint32_t size = observersCopy.Length(); + MOZ_ASSERT(mBroadcastCopy.IsEmpty()); + mBroadcastCopy = mObservers; + uint32_t size = mBroadcastCopy.Length(); for (uint32_t i = 0; i < size; ++i) { - observersCopy[i]->Notify(aParam); + // nulled if Removed during Broadcast + if (mBroadcastCopy[i]) { + mBroadcastCopy[i]->Notify(aParam); + } } + mBroadcastCopy.Clear(); } protected: nsTArray<Observer<T>*> mObservers; + nsTArray<Observer<T>*> mBroadcastCopy; }; } // namespace mozilla #endif // mozilla_Observer_h