Bug 1702375 [wpt PR 28327] - Update docs to point directly at RuntimeEnabledFeatures...
[gecko.git] / dom / canvas / CacheInvalidator.h
blob2bc226c02dc76c5b682eaf512d50738051459ba3
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 <unordered_map>
13 #include <unordered_set>
14 #include <vector>
16 // -
18 namespace mozilla {
20 class AbstractCache;
22 // -
24 class CacheInvalidator {
25 friend class AbstractCache;
27 private:
28 mutable std::unordered_set<AbstractCache*> mCaches;
30 public:
31 virtual ~CacheInvalidator() {
32 // It's actually generally unsafe to wait until now to invalidate caches,
33 // because when used as a mixin, this dtor is called after the dtor for the
34 // derived class. This means that if the derived class holds a cache (or is
35 // a cache!), OnInvalidate() will be called on a destroyed object.
36 // MOZ_ASSERT(!mCaches);
37 InvalidateCaches();
40 void InvalidateCaches() const;
43 // -
45 class AbstractCache {
46 typedef std::vector<const CacheInvalidator*> InvalidatorListT;
48 private:
49 InvalidatorListT mInvalidators;
51 public:
52 AbstractCache() = default;
54 explicit AbstractCache(InvalidatorListT&& invalidators) {
55 ResetInvalidators(std::move(invalidators));
58 virtual ~AbstractCache() { ResetInvalidators({}); }
60 public:
61 virtual void OnInvalidate() = 0;
63 void ResetInvalidators(InvalidatorListT&&);
64 void AddInvalidator(const CacheInvalidator&);
67 // -
69 template <typename T>
70 class CacheMaybe : public AbstractCache {
71 Maybe<T> mVal;
73 public:
74 template <typename U>
75 CacheMaybe& operator=(Maybe<U>&& rhs) {
76 mVal.reset();
77 if (rhs) {
78 mVal.emplace(std::move(rhs.ref()));
80 return *this;
83 CacheMaybe& operator=(Nothing) { return *this = Maybe<T>(); }
85 void OnInvalidate() override {
86 *this = Nothing();
87 ResetInvalidators({});
90 explicit operator bool() const { return bool(mVal); }
91 T* get() const { return mVal.ptrOr(nullptr); }
92 T* operator->() const { return get(); }
95 // -
97 template <typename KeyT, typename ValueT>
98 class CacheWeakMap final {
99 class Entry final : public AbstractCache {
100 public:
101 CacheWeakMap& mParent;
102 const KeyT mKey;
103 const ValueT mValue;
105 Entry(CacheWeakMap& parent, const KeyT& key, ValueT&& value)
106 : mParent(parent), mKey(key), mValue(std::move(value)) {}
108 void OnInvalidate() override {
109 const auto erased = mParent.mMap.erase(&mKey);
110 MOZ_ALWAYS_TRUE(erased == 1);
114 struct DerefHash final {
115 size_t operator()(const KeyT* const a) const {
116 return std::hash<KeyT>()(*a);
119 struct DerefEqual final {
120 bool operator()(const KeyT* const a, const KeyT* const b) const {
121 return *a == *b;
125 typedef std::unordered_map<const KeyT*, UniquePtr<Entry>, DerefHash,
126 DerefEqual>
127 MapT;
128 MapT mMap;
130 public:
131 UniquePtr<Entry> MakeEntry(const KeyT& key, ValueT&& value) {
132 return UniquePtr<Entry>(new Entry(*this, key, std::move(value)));
134 UniquePtr<Entry> MakeEntry(const KeyT& key, const ValueT& value) {
135 return MakeEntry(key, ValueT(value));
138 const ValueT* Insert(UniquePtr<Entry>&& entry) {
139 auto insertable = typename MapT::value_type{&entry->mKey, std::move(entry)};
141 const auto res = mMap.insert(std::move(insertable));
142 const auto& didInsert = res.second;
143 MOZ_ALWAYS_TRUE(didInsert);
145 const auto& itr = res.first;
146 return &itr->second->mValue;
149 const ValueT* Find(const KeyT& key) const {
150 const auto itr = mMap.find(&key);
151 if (itr == mMap.end()) return nullptr;
153 return &itr->second->mValue;
156 void Clear() const {
157 while (true) {
158 const auto itr = mMap.begin();
159 if (itr == mMap.end()) return;
160 itr->second->OnInvalidate();
164 ~CacheWeakMap() { Clear(); }
167 } // namespace mozilla
169 #endif // MOZILLA_CACHE_INVALIDATOR_H_