#ifndef MemoryCache_h
#define MemoryCache_h
#include "core/fetch/Resource.h"
#include "core/fetch/ResourcePtr.h"
#include "public/platform/WebThread.h"
#include "wtf/HashMap.h"
#include "wtf/Noncopyable.h"
#include "wtf/Vector.h"
#include "wtf/text/StringHash.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
class CSSStyleSheetResource;
class Resource;
class ResourceFetcher;
class KURL;
class ExecutionContext;
class SecurityOrigin;
struct SecurityOriginHash;
#undef MEMORY_CACHE_STATS
class MemoryCache FINAL : public blink::WebThread::TaskObserver {
WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
public:
MemoryCache();
virtual ~MemoryCache();
class MemoryCacheEntry {
public:
static PassOwnPtr<MemoryCacheEntry> create(Resource* resource) { return adoptPtr(new MemoryCacheEntry(resource)); }
ResourcePtr<Resource> m_resource;
bool m_inLiveDecodedResourcesList;
unsigned m_accessCount;
MemoryCacheEntry* m_previousInLiveResourcesList;
MemoryCacheEntry* m_nextInLiveResourcesList;
MemoryCacheEntry* m_previousInAllResourcesList;
MemoryCacheEntry* m_nextInAllResourcesList;
private:
MemoryCacheEntry(Resource* resource)
: m_resource(resource)
, m_inLiveDecodedResourcesList(false)
, m_accessCount(0)
, m_previousInLiveResourcesList(0)
, m_nextInLiveResourcesList(0)
, m_previousInAllResourcesList(0)
, m_nextInAllResourcesList(0)
{
}
};
struct LRUList {
MemoryCacheEntry* m_head;
MemoryCacheEntry* m_tail;
LRUList() : m_head(0), m_tail(0) { }
};
struct TypeStatistic {
int count;
int size;
int liveSize;
int decodedSize;
int encodedSize;
int encodedSizeDuplicatedInDataURLs;
int purgeableSize;
int purgedSize;
TypeStatistic()
: count(0)
, size(0)
, liveSize(0)
, decodedSize(0)
, encodedSize(0)
, encodedSizeDuplicatedInDataURLs(0)
, purgeableSize(0)
, purgedSize(0)
{
}
void addResource(Resource*);
};
struct Statistics {
TypeStatistic images;
TypeStatistic cssStyleSheets;
TypeStatistic scripts;
TypeStatistic xslStyleSheets;
TypeStatistic fonts;
TypeStatistic other;
};
Resource* resourceForURL(const KURL&);
void add(Resource*);
void replace(Resource* newResource, Resource* oldResource);
void remove(Resource*);
bool contains(const Resource*) const;
static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL);
void setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t totalBytes);
void setDelayBeforeLiveDecodedPrune(double seconds) { m_delayBeforeLiveDecodedPrune = seconds; }
void setMaxPruneDeferralDelay(double seconds) { m_maxPruneDeferralDelay = seconds; }
void evictResources();
void prune(Resource* justReleasedResource = 0);
void update(Resource*, size_t oldSize, size_t newSize, bool wasAccessed = false);
void updateForAccess(Resource* resource) { update(resource, resource->size(), resource->size(), true); }
void insertInLiveDecodedResourcesList(Resource*);
void removeFromLiveDecodedResourcesList(Resource*);
bool isInLiveDecodedResourcesList(Resource*);
void addToLiveResourcesSize(Resource*);
void removeFromLiveResourcesSize(Resource*);
static void removeURLFromCache(ExecutionContext*, const KURL&);
Statistics getStatistics();
size_t minDeadCapacity() const { return m_minDeadCapacity; }
size_t maxDeadCapacity() const { return m_maxDeadCapacity; }
size_t capacity() const { return m_capacity; }
size_t liveSize() const { return m_liveSize; }
size_t deadSize() const { return m_deadSize; }
virtual void willProcessTask() OVERRIDE;
virtual void didProcessTask() OVERRIDE;
private:
LRUList* lruListFor(unsigned accessCount, size_t);
#ifdef MEMORY_CACHE_STATS
void dumpStats(Timer<MemoryCache>*);
void dumpLRULists(bool includeLive) const;
#endif
void insertInLRUList(MemoryCacheEntry*, LRUList*);
void removeFromLRUList(MemoryCacheEntry*, LRUList*);
size_t liveCapacity() const;
size_t deadCapacity() const;
void pruneDeadResources();
void pruneLiveResources();
void pruneNow(double currentTime);
bool evict(MemoryCacheEntry*);
static void removeURLFromCacheInternal(ExecutionContext*, const KURL&);
bool m_inPruneResources;
bool m_prunePending;
double m_maxPruneDeferralDelay;
double m_pruneTimeStamp;
double m_pruneFrameTimeStamp;
size_t m_capacity;
size_t m_minDeadCapacity;
size_t m_maxDeadCapacity;
size_t m_maxDeferredPruneDeadCapacity;
double m_delayBeforeLiveDecodedPrune;
size_t m_liveSize;
size_t m_deadSize;
Vector<LRUList, 32> m_allResources;
LRUList m_liveDecodedResources[Resource::CacheLiveResourcePriorityHigh + 1];
typedef HashMap<String, OwnPtr<MemoryCacheEntry> > ResourceMap;
ResourceMap m_resources;
friend class MemoryCacheTest;
#ifdef MEMORY_CACHE_STATS
Timer<MemoryCache> m_statsTimer;
#endif
};
MemoryCache* memoryCache();
void setMemoryCacheForTesting(MemoryCache*);
}
#endif