diff --git a/xpcom/ds/nsExpirationTracker.h b/xpcom/ds/nsExpirationTracker.h index 145a20b51d..672256d1dc 100644 --- a/xpcom/ds/nsExpirationTracker.h +++ b/xpcom/ds/nsExpirationTracker.h @@ -322,6 +322,20 @@ protected: */ virtual void NotifyExpiredLocked(T*, const AutoLock&) = 0; + /** + * This may be overridden to perform any post-aging work that needs to be + * done while still holding the lock. It will be called once after each timer + * event, and each low memory event has been handled. + */ + virtual void NotifyHandlerEndLocked(const AutoLock&) { }; + + /** + * This may be overridden to perform any post-aging work that needs to be + * done outside the lock. It will be called once after each + * NotifyEndTransactionLocked call. + */ + virtual void NotifyHandlerEnd() { }; + virtual Mutex& GetMutex() = 0; private: @@ -364,18 +378,26 @@ private: }; void HandleLowMemory() { - AutoLock lock(GetMutex()); - AgeAllGenerationsLocked(lock); + { + AutoLock lock(GetMutex()); + AgeAllGenerationsLocked(lock); + NotifyHandlerEndLocked(lock); + } + NotifyHandlerEnd(); } void HandleTimeout() { - AutoLock lock(GetMutex()); - AgeOneGenerationLocked(lock); - // Cancel the timer if we have no objects to track - if (IsEmptyLocked(lock)) { - mTimer->Cancel(); - mTimer = nullptr; + { + AutoLock lock(GetMutex()); + AgeOneGenerationLocked(lock); + // Cancel the timer if we have no objects to track + if (IsEmptyLocked(lock)) { + mTimer->Cancel(); + mTimer = nullptr; + } + NotifyHandlerEndLocked(lock); } + NotifyHandlerEnd(); } static void TimerCallback(nsITimer* aTimer, void* aThis) @@ -449,6 +471,14 @@ class nsExpirationTracker : protected ::detail::SingleThreadedExpirationTracker< NotifyExpired(aObject); } + /** + * Since there are no users of these callbacks in the single threaded case, + * we mark them as final with the hope that the compiler can optimize the + * method calls out entirely. + */ + void NotifyHandlerEndLocked(const AutoLock&) final override { } + void NotifyHandlerEnd() final override { } + protected: virtual void NotifyExpired(T* aObj) = 0;