/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */
/** * This class is what is cached. It need to be allocated in an object separated * to the cache entry to be able to be tracked by the nsExpirationTracker.
* */ struct GradientCacheData {
GradientCacheData(GradientStops* aStops, GradientCacheKey&& aKey)
: mStops(aStops), mKey(std::move(aKey)) {}
/** * This class implements a cache, that retains the GradientStops used to draw * the gradients. * * An entry stays in the cache as long as it is used often and we don't exceed * the maximum, in which case the most recently used will be kept.
*/ class GradientCache; using GradientCacheMutex = StaticDataMutex<UniquePtr<GradientCache>>; class MOZ_RAII LockedInstance { public: explicit LockedInstance(GradientCacheMutex& aDataMutex)
: mAutoLock(aDataMutex.Lock()) {}
UniquePtr<GradientCache>& operator->() const& { return mAutoLock.ref(); }
UniquePtr<GradientCache>& operator->() const&& = delete;
UniquePtr<GradientCache>& operator*() const& { return mAutoLock.ref(); }
UniquePtr<GradientCache>& operator*() const&& = delete; explicitoperatorbool() const { return !!mAutoLock.ref(); }
stops = aCreateFunc(); if (!stops) { return nullptr;
}
auto data = MakeUnique<GradientCacheData>(stops, GradientCacheKey(&aKey));
nsresult rv = lockedInstance->AddObjectLocked(data.get(), lockedInstance); if (NS_FAILED(rv)) { // We are OOM, and we cannot track this object. We don't want to store // entries in the hash table (since the expiration tracker is // responsible for removing the cache entries), so we avoid putting that // entry in the table, which is a good thing considering we are short on // memory anyway, we probably don't want to retain things. return stops.forget();
}
lockedInstance->mHashEntries.InsertOrUpdate(aKey, std::move(data));
numberOfEntries = lockedInstance->mHashEntries.Count();
}
if (numberOfEntries > MAX_ENTRIES) { // We have too many entries force the cache to age a generation.
NS_DispatchToMainThread(
NS_NewRunnableFunction("GradientCache::OnMaxEntriesBreached", [] {
LockedInstance lockedInstance(sInstanceMutex); if (!lockedInstance) { return;
}
lockedInstance->AgeOneGenerationLocked(lockedInstance);
lockedInstance->NotifyHandlerEndLocked(lockedInstance);
}));
}
return stops.forget();
}
GradientCacheMutex& GetMutex() final { return sInstanceMutex; }
void NotifyExpiredLocked(GradientCacheData* aObject, const LockedInstance& aLockedInstance) final { // Remove the gradient from the tracker.
RemoveObjectLocked(aObject, aLockedInstance);
// If entry exists move the data to mRemovedGradientData because we want to // drop it outside of the lock.
Maybe<UniquePtr<GradientCacheData>> gradientData =
mHashEntries.Extract(aObject->mKey); if (gradientData.isSome()) {
mRemovedGradientData.AppendElement(std::move(*gradientData));
}
}
// On Windows some of the Direct2D objects associated with the gradient stops // can be quite large, so we limit the number of cache entries. staticconst uint32_t MAX_ENTRIES = 4000; static GradientCacheMutex sInstanceMutex;
[[nodiscard]] staticbool EnsureInstanceLocked(
LockedInstance& aLockedInstance) { if (!aLockedInstance) { // GradientCache must be created on the main thread. if (!NS_IsMainThread()) { // This should only happen at shutdown, we fall back to not caching. returnfalse;
}
*aLockedInstance = MakeUnique<GradientCache>();
} returntrue;
}
/** * FIXME use nsTHashtable to avoid duplicating the GradientCacheKey. * https://bugzilla.mozilla.org/show_bug.cgi?id=761393#c47
*/
nsClassHashtable<GradientCacheKey, GradientCacheData> mHashEntries;
nsTArray<UniquePtr<GradientCacheData>> mRemovedGradientData;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.