blob: 225d455e49403d18c948d49285b82907da297d35 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_MEMORY_CACHE_H_
#define GPU_COMMAND_BUFFER_SERVICE_MEMORY_CACHE_H_
#include "base/containers/flat_set.h"
#include "base/containers/heap_array.h"
#include "base/containers/linked_list.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_provider.h"
#include "gpu/gpu_gles2_export.h"
namespace gpu {
// MemoryCacheEntry class for LRU tracking and holding key/value pair.
class GPU_GLES2_EXPORT MemoryCacheEntry
: public base::LinkNode<MemoryCacheEntry>,
public base::RefCountedThreadSafe<MemoryCacheEntry> {
public:
MemoryCacheEntry(std::string_view key, base::span<const uint8_t> data);
MemoryCacheEntry(std::string_view key, base::HeapArray<uint8_t> data);
std::string_view Key() const;
size_t TotalSize() const;
size_t DataSize() const;
base::span<const uint8_t> Data() const;
size_t ReadData(void* value_out, size_t value_size) const;
private:
friend class base::RefCountedThreadSafe<MemoryCacheEntry>;
~MemoryCacheEntry();
const std::string key_;
const base::HeapArray<uint8_t> data_;
};
class GPU_GLES2_EXPORT MemoryCache : public base::RefCounted<MemoryCache> {
public:
explicit MemoryCache(size_t max_size,
std::string_view cache_hit_trace_event = "");
scoped_refptr<MemoryCacheEntry> Store(std::string_view key,
base::span<const uint8_t> data);
scoped_refptr<MemoryCacheEntry> Store(std::string_view key,
base::HeapArray<uint8_t> data);
scoped_refptr<MemoryCacheEntry> Find(std::string_view key);
void PurgeMemory(base::MemoryPressureLevel memory_pressure_level);
void OnMemoryDump(const std::string& dump_name,
base::trace_event::ProcessMemoryDump* pmd);
template <typename Fn>
void ForEach(Fn fn) {
base::AutoLock lock(mutex_);
for (auto* node = lru_.head(); node != lru_.end(); node = node->next()) {
fn(node->value());
}
}
private:
// Overrides for transparent flat_set lookups using a string.
friend bool operator<(const scoped_refptr<MemoryCacheEntry>& lhs,
const scoped_refptr<MemoryCacheEntry>& rhs);
friend bool operator<(const scoped_refptr<MemoryCacheEntry>& lhs,
std::string_view rhs);
friend bool operator<(std::string_view lhs,
const scoped_refptr<MemoryCacheEntry>& rhs);
friend class base::RefCounted<MemoryCache>;
~MemoryCache();
void EvictEntry(std::string_view key) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void EvictEntry(MemoryCacheEntry* entry) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void InsertEntry(scoped_refptr<MemoryCacheEntry> entry)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool CanFitMemoryCacheEntry(size_t data_size) const;
base::Lock mutex_;
base::flat_set<scoped_refptr<MemoryCacheEntry>> entries_ GUARDED_BY(mutex_);
base::LinkedList<MemoryCacheEntry> lru_ GUARDED_BY(mutex_);
const size_t max_size_;
size_t current_size_ GUARDED_BY(mutex_) = 0;
const std::string cache_hit_trace_event_;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_MEMORY_CACHE_H_