blob: 43b632def3705d0b691898115ddd608c227bbf83 [file] [log] [blame]
* Copyright 2014, The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#include "ResourceProvider.h"
#include <list>
#include <memory>
#include <string>
#include <unordered_map>
namespace android {
namespace caze {
// Fixed size in-memory resource cache with ability to resize itself to an arbitrary size while
// minimizing invalidation of resources in the cache. It uses a ring buffer to store the cache and
// starts invalidating cache entries from the oldest to the newest when more space is required.
// The state of the cache is one of the following, using the implementation's iterators:
// | free space (empty cache, iterators are not valid) |
// | last and next block | free space (only one block is in the cache) |
// | free space | next block | occupied space | last block | padding |
// | occupied space | last block | free space | next block | occupied space | padding |
class ResourceInMemoryCache : public ResourceProvider {
// Creates a new in-memory cache with the given fallback provider and base address. The initial
// cache size is 0 byte.
static std::unique_ptr<ResourceInMemoryCache> create(
std::unique_ptr<ResourceProvider> fallbackProvider, void* baseAddress);
// If the requested resource is in the cache, copies it to the given memory address. If it
// isn't in the cache then requests it from the fallback provider and saves it into the cache
// if it fits (smaller than or equal to the size of the full cache).
bool get(const ResourceId& id, const GazerConnection& gazer, void* target,
uint32_t size) override;
// No prefetching is done for this provider because of the limited size of the in memory cache
// and because there is no performance gain if we fetch multiple resources at the same time
// compared to the case when we fetch them one by one. The prefetch request is forwarded to the
// fallback provider for possible prefetching after filtering out resources already present in
// the cache.
bool prefetch(const ResourceList& resources,
const GazerConnection& gazer, void* buffer, uint32_t size) override;
// Resizes the memory region used by the cache, modifying the end of its memory region.
// Resources falling outside of the new memory region will be evicted from the cache.
void updateSize(size_t newSize);
// Data structure representing a cached resource including its resource id and the offset of
// its memory location, relative to the base address of the cache. Begin is the offset of the
// first byte and end is the offset of the byte immediately after the end of the resource. The
// size of the resource is (end - begin).
struct Entry {
Entry(const ResourceId& id, size_t begin, size_t end);
ResourceId id;
size_t begin;
size_t end;
ResourceInMemoryCache(std::unique_ptr<ResourceProvider> fallbackProvider, void* baseAddress);
// Allocates the given amount of memory inside the resource cache for the resource with the
// provided resource id (required for later bookkeeping). If the allocation was successful (the
// requested memory is smaller then the size of the cache) then returns the base address of the
// allocated region, otherwise returns a null pointer,
uint8_t* allocateMemory(const std::string& id, size_t size);
// Fallback provider for the case when the requested resource is not in the cache.
std::unique_ptr<ResourceProvider> mFallbackProvider;
// The base address and the size of the memory used for caching. This memory region is owned by
// the memory manager class, not by the cache itself.
uint8_t* mBaseAddress;
size_t mSize;
// The list of resources currently in the cache with their location.
std::list<Entry> mBlockList;
// Iterator pointing to the last block inserted in the cache.
std::list<Entry>::iterator mLastBlock;
// Iterator pointing to the next block to be removed from the cache.
std::list<Entry>::iterator mNextBlock;
// The resources currently inside the cache. The value for each key is the offset of the
// resource inside the cache
std::unordered_map<ResourceId, size_t> mCache;
} // end of namespace caze
} // end of namespace android