Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / canvas / CacheInvalidator.h
blob909aacfc378a8a38d13c551cc23f564efc402724
1 /* -*- Mode: C++; tab-width: 13; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=13 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_CACHE_INVALIDATOR_H_
8 #define MOZILLA_CACHE_INVALIDATOR_H_
10 #include "mozilla/Maybe.h"
11 #include "mozilla/UniquePtr.h"
12 #include "DmdStdContainers.h"
13 #include <vector>
15 // -
17 namespace mozilla {
19 class AbstractCache;
21 // -
23 class CacheInvalidator {
24 friend class AbstractCache;
26 private:
27 mutable webgl::dmd_unordered_set<AbstractCache*> mCaches;
29 public:
30 virtual ~CacheInvalidator() {
31 // It's actually generally unsafe to wait until now to invalidate caches,
32 // because when used as a mixin, this dtor is called after the dtor for the
33 // derived class. This means that if the derived class holds a cache (or is
34 // a cache!), OnInvalidate() will be called on a destroyed object.
35 // MOZ_ASSERT(!mCaches);
36 InvalidateCaches();
39 void InvalidateCaches() const;
41 // -
43 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mso) const {
44 return mCaches.SizeOfExcludingThis(mso);
48 // -
50 class AbstractCache {
51 using InvalidatorListT = std::vector<const CacheInvalidator*>;
53 private:
54 InvalidatorListT mInvalidators;
56 public:
57 AbstractCache() = default;
59 explicit AbstractCache(InvalidatorListT&& invalidators) {
60 ResetInvalidators(std::move(invalidators));
63 virtual ~AbstractCache() { ResetInvalidators({}); }
65 public:
66 virtual void OnInvalidate() = 0;
68 void ResetInvalidators(InvalidatorListT&&);
69 void AddInvalidator(const CacheInvalidator&);
72 // -
74 template <typename T>
75 class CacheMaybe : public AbstractCache {
76 Maybe<T> mVal;
78 public:
79 template <typename U>
80 CacheMaybe& operator=(Maybe<U>&& rhs) {
81 mVal.reset();
82 if (rhs) {
83 mVal.emplace(std::move(rhs.ref()));
85 return *this;
88 CacheMaybe& operator=(Nothing) { return *this = Maybe<T>(); }
90 void OnInvalidate() override {
91 *this = Nothing();
92 ResetInvalidators({});
95 explicit operator bool() const { return bool(mVal); }
96 T* get() const { return mVal.ptrOr(nullptr); }
97 T* operator->() const { return get(); }
100 // -
102 template <typename KeyT, typename ValueT>
103 class CacheWeakMap final {
104 class Entry final : public AbstractCache {
105 public:
106 CacheWeakMap& mParent;
107 const KeyT mKey;
108 const ValueT mValue;
110 Entry(CacheWeakMap& parent, const KeyT& key, ValueT&& value)
111 : mParent(parent), mKey(key), mValue(std::move(value)) {}
113 void OnInvalidate() override {
114 const auto erased = mParent.mMap.erase(&mKey);
115 MOZ_ALWAYS_TRUE(erased == 1);
119 struct DerefHash final {
120 size_t operator()(const KeyT* const a) const {
121 return std::hash<KeyT>()(*a);
124 struct DerefEqual final {
125 bool operator()(const KeyT* const a, const KeyT* const b) const {
126 return *a == *b;
130 using MapT = webgl::dmd_unordered_map<const KeyT*, UniquePtr<Entry>,
131 DerefHash, DerefEqual>;
132 MapT mMap;
134 public:
135 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mso) const {
136 return mMap.SizeOfExcludingThis(mso);
139 UniquePtr<Entry> MakeEntry(const KeyT& key, ValueT&& value) {
140 return UniquePtr<Entry>(new Entry(*this, key, std::move(value)));
142 UniquePtr<Entry> MakeEntry(const KeyT& key, const ValueT& value) {
143 return MakeEntry(key, ValueT(value));
146 const ValueT* Insert(UniquePtr<Entry>&& entry) {
147 auto insertable = typename MapT::value_type{&entry->mKey, std::move(entry)};
149 const auto res = mMap.insert(std::move(insertable));
150 const auto& didInsert = res.second;
151 MOZ_ALWAYS_TRUE(didInsert);
153 const auto& itr = res.first;
154 return &itr->second->mValue;
157 const ValueT* Find(const KeyT& key) const {
158 const auto itr = mMap.find(&key);
159 if (itr == mMap.end()) return nullptr;
161 return &itr->second->mValue;
164 void Clear() const {
165 while (true) {
166 const auto itr = mMap.begin();
167 if (itr == mMap.end()) return;
168 itr->second->OnInvalidate();
172 ~CacheWeakMap() { Clear(); }
175 } // namespace mozilla
177 #endif // MOZILLA_CACHE_INVALIDATOR_H_