2017-10-30 23:56:18 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 13; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim: set ts=13 sts=4 et sw=4 tw=90: */
|
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
#ifndef MOZILLA_CACHE_MAP_H_
|
|
|
|
#define MOZILLA_CACHE_MAP_H_
|
|
|
|
|
|
|
|
#include "mozilla/UniquePtr.h"
|
|
|
|
#include <map>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
namespace detail {
|
2017-11-16 05:44:38 +03:00
|
|
|
class CacheMapUntypedEntry;
|
2017-10-30 23:56:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
class CacheMapInvalidator
|
|
|
|
{
|
2017-11-16 05:44:38 +03:00
|
|
|
friend class detail::CacheMapUntypedEntry;
|
2017-10-30 23:56:18 +03:00
|
|
|
|
|
|
|
mutable std::unordered_set<const detail::CacheMapUntypedEntry*> mCacheEntries;
|
|
|
|
|
|
|
|
public:
|
|
|
|
~CacheMapInvalidator() {
|
|
|
|
InvalidateCaches();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InvalidateCaches() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
2017-11-16 05:44:38 +03:00
|
|
|
class CacheMapUntypedEntry
|
2017-10-30 23:56:18 +03:00
|
|
|
{
|
|
|
|
template<typename, typename> friend class CacheMap;
|
|
|
|
|
2017-11-16 05:44:38 +03:00
|
|
|
private:
|
2017-10-30 23:56:18 +03:00
|
|
|
const std::vector<const CacheMapInvalidator*> mInvalidators;
|
|
|
|
|
2017-11-16 05:44:38 +03:00
|
|
|
protected:
|
2017-10-30 23:56:18 +03:00
|
|
|
CacheMapUntypedEntry(std::vector<const CacheMapInvalidator*>&& invalidators);
|
|
|
|
~CacheMapUntypedEntry();
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual void Invalidate() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DerefLess final {
|
2017-11-16 05:44:38 +03:00
|
|
|
template<typename T>
|
2017-10-30 23:56:18 +03:00
|
|
|
bool operator ()(const T* const a, const T* const b) const {
|
|
|
|
return *a < *b;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
|
|
|
|
template<typename KeyT, typename ValueT>
|
|
|
|
class CacheMap final
|
|
|
|
{
|
2017-11-16 05:44:38 +03:00
|
|
|
class Entry final : public detail::CacheMapUntypedEntry {
|
|
|
|
public:
|
2017-10-30 23:56:18 +03:00
|
|
|
CacheMap& mParent;
|
|
|
|
const KeyT mKey;
|
|
|
|
const ValueT mValue;
|
|
|
|
|
|
|
|
Entry(std::vector<const CacheMapInvalidator*>&& invalidators, CacheMap& parent,
|
|
|
|
KeyT&& key, ValueT&& value)
|
2018-05-30 22:15:35 +03:00
|
|
|
: detail::CacheMapUntypedEntry(std::move(invalidators))
|
2017-10-30 23:56:18 +03:00
|
|
|
, mParent(parent)
|
2018-05-30 22:15:35 +03:00
|
|
|
, mKey(std::move(key))
|
|
|
|
, mValue(std::move(value))
|
2017-10-30 23:56:18 +03:00
|
|
|
{ }
|
|
|
|
|
|
|
|
void Invalidate() const override {
|
|
|
|
const auto erased = mParent.mMap.erase(&mKey);
|
|
|
|
MOZ_ALWAYS_TRUE( erased == 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator <(const Entry& x) const {
|
|
|
|
return mKey < x.mKey;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-11-16 05:44:38 +03:00
|
|
|
typedef std::map<const KeyT*, UniquePtr<const Entry>, detail::DerefLess> MapT;
|
2017-10-30 23:56:18 +03:00
|
|
|
MapT mMap;
|
|
|
|
|
|
|
|
public:
|
|
|
|
const ValueT* Insert(KeyT&& key, ValueT&& value,
|
|
|
|
std::vector<const CacheMapInvalidator*>&& invalidators)
|
|
|
|
{
|
2018-05-30 22:15:35 +03:00
|
|
|
UniquePtr<const Entry> entry( new Entry(std::move(invalidators), *this, std::move(key),
|
|
|
|
std::move(value)) );
|
2017-10-30 23:56:18 +03:00
|
|
|
|
|
|
|
typename MapT::value_type insertable{
|
|
|
|
&entry->mKey,
|
|
|
|
nullptr
|
|
|
|
};
|
2018-05-30 22:15:35 +03:00
|
|
|
insertable.second = std::move(entry);
|
2017-10-30 23:56:18 +03:00
|
|
|
|
2018-05-30 22:15:35 +03:00
|
|
|
const auto res = mMap.insert(std::move(insertable));
|
2017-10-30 23:56:18 +03:00
|
|
|
const auto& didInsert = res.second;
|
|
|
|
MOZ_ALWAYS_TRUE( didInsert );
|
|
|
|
|
|
|
|
const auto& itr = res.first;
|
|
|
|
return &itr->second->mValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ValueT* Find(const KeyT& key) const {
|
|
|
|
const auto itr = mMap.find(&key);
|
|
|
|
if (itr == mMap.end())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return &itr->second->mValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Invalidate() {
|
|
|
|
while (mMap.size()) {
|
|
|
|
const auto& itr = mMap.begin();
|
|
|
|
itr->second->Invalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // MOZILLA_CACHE_MAP_H_
|