| Index: chrome/common/mru_cache.h
|
| ===================================================================
|
| --- chrome/common/mru_cache.h (revision 78451)
|
| +++ chrome/common/mru_cache.h (working copy)
|
| @@ -1,253 +0,0 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -// This file contains a template for a Most Recently Used cache that allows
|
| -// constant-time access to items using a key, but easy identification of the
|
| -// least-recently-used items for removal. Each key can only be associated with
|
| -// one payload item at a time.
|
| -//
|
| -// The key object will be stored twice, so it should support efficient copying.
|
| -//
|
| -// NOTE: While all operations are O(1), this code is written for
|
| -// legibility rather than optimality. If future profiling identifies this as
|
| -// a bottleneck, there is room for smaller values of 1 in the O(1). :]
|
| -
|
| -#ifndef CHROME_COMMON_MRU_CACHE_H__
|
| -#define CHROME_COMMON_MRU_CACHE_H__
|
| -#pragma once
|
| -
|
| -#include <list>
|
| -#include <map>
|
| -#include <utility>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/logging.h"
|
| -
|
| -// MRUCacheBase ----------------------------------------------------------------
|
| -
|
| -// Base class for the MRU cache specializations defined below.
|
| -// The deletor will get called on all payloads that are being removed or
|
| -// replaced.
|
| -template <class KeyType, class PayloadType, class DeletorType>
|
| -class MRUCacheBase {
|
| - public:
|
| - // The payload of the list. This maintains a copy of the key so we can
|
| - // efficiently delete things given an element of the list.
|
| - typedef std::pair<KeyType, PayloadType> value_type;
|
| -
|
| - private:
|
| - typedef std::list<value_type> PayloadList;
|
| - typedef std::map<KeyType, typename PayloadList::iterator> KeyIndex;
|
| -
|
| - public:
|
| - typedef typename PayloadList::size_type size_type;
|
| -
|
| - typedef typename PayloadList::iterator iterator;
|
| - typedef typename PayloadList::const_iterator const_iterator;
|
| - typedef typename PayloadList::reverse_iterator reverse_iterator;
|
| - typedef typename PayloadList::const_reverse_iterator const_reverse_iterator;
|
| -
|
| - enum { NO_AUTO_EVICT = 0 };
|
| -
|
| - // The max_size is the size at which the cache will prune its members to when
|
| - // a new item is inserted. If the caller wants to manager this itself (for
|
| - // example, maybe it has special work to do when something is evicted), it
|
| - // can pass NO_AUTO_EVICT to not restrict the cache size.
|
| - explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {
|
| - }
|
| -
|
| - virtual ~MRUCacheBase() {
|
| - iterator i = begin();
|
| - while (i != end())
|
| - i = Erase(i);
|
| - }
|
| -
|
| - // Inserts a payload item with the given key. If an existing item has
|
| - // the same key, it is removed prior to insertion. An iterator indicating the
|
| - // inserted item will be returned (this will always be the front of the list).
|
| - //
|
| - // The payload will be copied. In the case of an OwningMRUCache, this function
|
| - // will take ownership of the pointer.
|
| - iterator Put(const KeyType& key, const PayloadType& payload) {
|
| - // Remove any existing payload with that key.
|
| - typename KeyIndex::iterator index_iter = index_.find(key);
|
| - if (index_iter != index_.end()) {
|
| - // Erase the reference to it. This will call the deletor on the removed
|
| - // element. The index reference will be replaced in the code below.
|
| - Erase(index_iter->second);
|
| - } else if (max_size_ != NO_AUTO_EVICT) {
|
| - // New item is being inserted which might make it larger than the maximum
|
| - // size: kick the oldest thing out if necessary.
|
| - ShrinkToSize(max_size_ - 1);
|
| - }
|
| -
|
| - ordering_.push_front(value_type(key, payload));
|
| - index_[key] = ordering_.begin();
|
| - return ordering_.begin();
|
| - }
|
| -
|
| - // Retrieves the contents of the given key, or end() if not found. This method
|
| - // has the side effect of moving the requested item to the front of the
|
| - // recency list.
|
| - //
|
| - // TODO(brettw) We may want a const version of this function in the future.
|
| - iterator Get(const KeyType& key) {
|
| - typename KeyIndex::iterator index_iter = index_.find(key);
|
| - if (index_iter == index_.end())
|
| - return end();
|
| - typename PayloadList::iterator iter = index_iter->second;
|
| -
|
| - // Move the touched item to the front of the recency ordering.
|
| - ordering_.splice(ordering_.begin(), ordering_, iter);
|
| - return ordering_.begin();
|
| - }
|
| -
|
| - // Retrieves the payload associated with a given key and returns it via
|
| - // result without affecting the ordering (unlike Get).
|
| - //
|
| - // TODO(brettw) We may want a const version of this function in the future.
|
| - iterator Peek(const KeyType& key) {
|
| - typename KeyIndex::const_iterator index_iter = index_.find(key);
|
| - if (index_iter == index_.end())
|
| - return end();
|
| - return index_iter->second;
|
| - }
|
| -
|
| - // Erases the item referenced by the given iterator. An iterator to the item
|
| - // following it will be returned. The iterator must be valid.
|
| - iterator Erase(iterator pos) {
|
| - deletor_(pos->second);
|
| - index_.erase(pos->first);
|
| - return ordering_.erase(pos);
|
| - }
|
| -
|
| - // MRUCache entries are often processed in reverse order, so we add this
|
| - // convenience function (not typically defined by STL containers).
|
| - reverse_iterator Erase(reverse_iterator pos) {
|
| - // We have to actually give it the incremented iterator to delete, since
|
| - // the forward iterator that base() returns is actually one past the item
|
| - // being iterated over.
|
| - return reverse_iterator(Erase((++pos).base()));
|
| - }
|
| -
|
| - // Shrinks the cache so it only holds |new_size| items. If |new_size| is
|
| - // bigger or equal to the current number of items, this will do nothing.
|
| - void ShrinkToSize(size_type new_size) {
|
| - for (size_type i = size(); i > new_size; i--)
|
| - Erase(rbegin());
|
| - }
|
| -
|
| - // Deletes everything from the cache.
|
| - void Clear() {
|
| - for (typename PayloadList::iterator i(ordering_.begin());
|
| - i != ordering_.end(); ++i)
|
| - deletor_(i->second);
|
| - index_.clear();
|
| - ordering_.clear();
|
| - }
|
| -
|
| - // Returns the number of elements in the cache.
|
| - size_type size() const {
|
| - // We don't use ordering_.size() for the return value because
|
| - // (as a linked list) it can be O(n).
|
| - DCHECK(index_.size() == ordering_.size());
|
| - return index_.size();
|
| - }
|
| -
|
| - // Allows iteration over the list. Forward iteration starts with the most
|
| - // recent item and works backwards.
|
| - //
|
| - // Note that since these iterators are actually iterators over a list, you
|
| - // can keep them as you insert or delete things (as long as you don't delete
|
| - // the one you are pointing to) and they will still be valid.
|
| - iterator begin() { return ordering_.begin(); }
|
| - const_iterator begin() const { ordering_.begin(); }
|
| - iterator end() { return ordering_.end(); }
|
| - const_iterator end() const { return ordering_.end(); }
|
| -
|
| - reverse_iterator rbegin() { return ordering_.rbegin(); }
|
| - const_reverse_iterator rbegin() const { ordering_.rbegin(); }
|
| - reverse_iterator rend() { return ordering_.rend(); }
|
| - const_reverse_iterator rend() const { return ordering_.rend(); }
|
| -
|
| - bool empty() const { return ordering_.empty(); }
|
| -
|
| - private:
|
| - PayloadList ordering_;
|
| - KeyIndex index_;
|
| -
|
| - size_type max_size_;
|
| -
|
| - DeletorType deletor_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MRUCacheBase);
|
| -};
|
| -
|
| -// MRUCache --------------------------------------------------------------------
|
| -
|
| -// A functor that does nothing. Used by the MRUCache.
|
| -template<class PayloadType>
|
| -class MRUCacheNullDeletor {
|
| - public:
|
| - void operator()(PayloadType& payload) {
|
| - }
|
| -};
|
| -
|
| -// A container that does not do anything to free its data. Use this when storing
|
| -// value types (as opposed to pointers) in the list.
|
| -template <class KeyType, class PayloadType>
|
| -class MRUCache : public MRUCacheBase<KeyType,
|
| - PayloadType,
|
| - MRUCacheNullDeletor<PayloadType> > {
|
| - private:
|
| - typedef MRUCacheBase<KeyType, PayloadType,
|
| - MRUCacheNullDeletor<PayloadType> > ParentType;
|
| -
|
| - public:
|
| - // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
|
| - explicit MRUCache(typename ParentType::size_type max_size)
|
| - : ParentType(max_size) {
|
| - }
|
| - virtual ~MRUCache() {
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(MRUCache);
|
| -};
|
| -
|
| -// OwningMRUCache --------------------------------------------------------------
|
| -
|
| -template<class PayloadType>
|
| -class MRUCachePointerDeletor {
|
| - public:
|
| - void operator()(PayloadType& payload) {
|
| - delete payload;
|
| - }
|
| -};
|
| -
|
| -// A cache that owns the payload type, which must be a non-const pointer type.
|
| -// The pointers will be deleted when they are removed, replaced, or when the
|
| -// cache is destroyed.
|
| -template <class KeyType, class PayloadType>
|
| -class OwningMRUCache
|
| - : public MRUCacheBase<KeyType,
|
| - PayloadType,
|
| - MRUCachePointerDeletor<PayloadType> > {
|
| - private:
|
| - typedef MRUCacheBase<KeyType, PayloadType,
|
| - MRUCachePointerDeletor<PayloadType> > ParentType;
|
| -
|
| - public:
|
| - // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
|
| - explicit OwningMRUCache(typename ParentType::size_type max_size)
|
| - : ParentType(max_size) {
|
| - }
|
| - virtual ~OwningMRUCache() {
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(OwningMRUCache);
|
| -};
|
| -
|
| -#endif // CHROME_COMMON_MRU_CACHE_H__
|
|
|