Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Unified Diff: quiver/lib/src/collection/lru_map.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « quiver/lib/src/collection/delegates/set.dart ('k') | quiver/lib/src/collection/multimap.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: quiver/lib/src/collection/lru_map.dart
diff --git a/quiver/lib/src/collection/lru_map.dart b/quiver/lib/src/collection/lru_map.dart
deleted file mode 100644
index 13e094ac066e3229ffc6dac28cb9ccf25d6b0acc..0000000000000000000000000000000000000000
--- a/quiver/lib/src/collection/lru_map.dart
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// 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
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-part of quiver.collection;
-
-/**
- * An implementation of a [Map] which has a maximum size and uses a (Least
- * Recently Used)[http://en.wikipedia.org/wiki/Cache_algorithms#LRU] algorithm
- * to remove items from the [Map] when the [maximumSize] is reached and new
- * items are added.
- *
- * It is safe to access the [keys] and [values] collections without affecting
- * the "used" ordering - as well as using [forEach]. Other types of access,
- * including bracket, and [putIfAbsent], promotes the key-value pair to the MRU
- * position.
- */
-abstract class LruMap<K, V> implements Map<K, V> {
- /**
- * Creates a [LruMap] instance with the default implementation.
- */
- factory LruMap({int maximumSize}) = LinkedLruHashMap;
-
- /**
- * Maximum size of the [Map]. If [length] exceeds this value at any time,
- * n entries accessed the earliest are removed, where n is [length] -
- * [maximumSize].
- */
- int maximumSize;
-}
-
-/**
- * Simple implementation of a linked-list entry that contains a [key] and
- * [value].
- */
-class _LinkedEntry<K, V> {
- K key;
- V value;
-
- _LinkedEntry<K, V> next;
- _LinkedEntry<K, V> previous;
-
- _LinkedEntry([this.key, this.value]);
-}
-
-/**
- * A linked hash-table based implementation of [LruMap].
- */
-class LinkedLruHashMap<K, V> implements LruMap<K, V> {
- static const _DEFAULT_MAXIMUM_SIZE = 100;
-
- final Map<K, _LinkedEntry<K, V>> _entries;
-
- int _maximumSize;
-
- _LinkedEntry<K, V> _head;
- _LinkedEntry<K, V> _tail;
-
- /**
- * Create a new LinkedLruHashMap with a [maximumSize].
- */
- factory LinkedLruHashMap({int maximumSize}) =>
- new LinkedLruHashMap._fromMap(new HashMap<K, _LinkedEntry<K, V>>(),
- maximumSize: maximumSize);
-
- LinkedLruHashMap._fromMap(
- this._entries, {
- int maximumSize})
- // This pattern is used instead of a default value because we want to
- // be able to respect null values coming in from MapCache.lru.
- : _maximumSize = firstNonNull(maximumSize, _DEFAULT_MAXIMUM_SIZE);
-
- /**
- * Adds all key-value pairs of [other] to this map.
- *
- * The operation is equivalent to doing this[key] = value for each key and
- * associated value in other. It iterates over other, which must therefore not
- * change during the iteration.
- *
- * If a key of [other] is already in this map, its value is overwritten. If
- * the number of unique keys is greater than [maximumSize] then the least
- * recently use keys are evicted. For keys written to by [other], the least
- * recently user order is determined by [other]'s iteration order.
- */
- @override
- void addAll(Map<K, V> other) => other.forEach((k, v) => this[k] = v);
-
- @override
- void clear() {
- _entries.clear();
- _head = _tail = null;
- }
-
- @override
- bool containsKey(K key) => _entries.containsKey(key);
-
- @override
- bool containsValue(V value) => values.contains(value);
-
- /**
- * Applies [action] to each key-value pair of the map in order of MRU to LRU.
- *
- * Calling `action` must not add or remove keys from the map.
- */
- @override
- void forEach(void action(K key, V value)) {
- var head = _head;
- while (head != null) {
- action(head.key, head.value);
- head = head.next;
- }
- }
-
- @override
- int get length => _entries.length;
-
- @override
- bool get isEmpty => _entries.isEmpty;
-
- @override
- bool get isNotEmpty => _entries.isNotEmpty;
-
- /**
- * Creates an [Iterable] around the entries of the map.
- */
- Iterable<_LinkedEntry<K, V>> _iterable() {
- return new GeneratingIterable<_LinkedEntry<K, V>>(
- () => _head, (n) => n.next);
- }
-
- /**
- * The keys of [this] - in order of MRU to LRU.
- *
- * The returned iterable does *not* have efficient `length` or `contains`.
- */
- @override
- Iterable<K> get keys => _iterable().map((e) => e.key);
-
- /**
- * The values of [this] - in order of MRU to LRU.
- *
- * The returned iterable does *not* have efficient `length` or `contains`.
- */
- @override
- Iterable<V> get values => _iterable().map((e) => e.value);
-
- @override
- int get maximumSize => _maximumSize;
-
- @override
- void set maximumSize(int maximumSize) {
- if (maximumSize == null) throw new ArgumentError.notNull('maximumSize');
- while (length > maximumSize) {
- _removeLru();
- }
- _maximumSize = maximumSize;
- }
-
- /**
- * Look up the value associated with [key], or add a new value if it isn't
- * there. The pair is promoted to the MRU position.
- *
- * Otherwise calls [ifAbsent] to get a new value, associates [key] to that
- * [value], and then returns the new [value], with the key-value pair in the
- * MRU position. If this causes [length] to exceed [maximumSize], then the
- * LRU position is removed.
- */
- @override
- V putIfAbsent(K key, V ifAbsent()) {
- final entry = _entries.putIfAbsent(
- key, () => _createEntry(key, ifAbsent()));
- if (length > maximumSize) {
- _removeLru();
- }
- _promoteEntry(entry);
- return entry.value;
- }
-
- /**
- * Get the value for a [key] in the [Map]. The [key] will be promoted to the
- * 'Most Recently Used' position. *NOTE*: Calling [] inside an iteration over
- * keys/values is currently unsupported; use [keys] or [values] if you
- * need information about entries without modifying their position.
- */
- @override
- V operator[](K key) {
- final entry = _entries[key];
- if (entry != null) {
- _promoteEntry(entry);
- return entry.value;
- } else {
- return null;
- }
- }
-
- /**
- * If [key] already exists, promotes it to the MRU position & assigns [value].
- *
- * Otherwise, adds [key] and [value] to the MRU position.
- * If [length] exceeds [maximumSize] while adding, removes the LRU position.
- */
- @override
- void operator []=(K key, V value) {
- // Add this item to the MRU position.
- _insertMru(_createEntry(key, value));
-
- // Remove the LRU item if the size would be exceeded by adding this item.
- if (length > maximumSize) {
- assert(length == maximumSize + 1);
- _removeLru();
- }
- }
-
- @override
- V remove(K key) {
- final entry = _entries.remove(key);
- if (entry != null) {
- if (entry == _head) {
- _head = _head.next;
- } else if (entry == _tail) {
- _tail.previous.next = null;
- _tail = _tail.previous;
- } else {
- entry.previous.next = entry.next;
- }
- return entry.value;
- }
- return null;
- }
-
- @override
- String toString() => Maps.mapToString(this);
-
- /**
- * Moves [entry] to the MRU position, shifting the linked list if necessary.
- */
- void _promoteEntry(_LinkedEntry<K, V> entry) {
- if (entry.previous != null) {
- // If already existed in the map, link previous to next.
- entry.previous.next = entry.next;
-
- // If this was the tail element, assign a new tail.
- if (_tail == entry) {
- _tail = entry.previous;
- }
- }
-
- // Replace head with this element.
- if (_head != null) {
- _head.previous = entry;
- }
- entry.previous = null;
- entry.next = _head;
- _head = entry;
-
- // Add a tail if this is the first element.
- if (_tail == null) {
- assert(length == 1);
- _tail = _head;
- }
- }
-
- /**
- * Creates and returns an entry from [key] and [value].
- */
- _LinkedEntry<K, V> _createEntry(K key, V value) {
- return new _LinkedEntry<K, V>(key, value);
- }
-
- /**
- * If [entry] does not exist, inserts it into the backing map.
- * If it does, replaces the existing [_LinkedEntry.value] with [entry.value].
- * Then, in either case, promotes [entry] to the MRU position.
- */
- void _insertMru(_LinkedEntry<K, V> entry) {
- // Insert a new entry if necessary (only 1 hash lookup in entire function).
- // Otherwise, just updates the existing value.
- final value = entry.value;
- _promoteEntry(_entries.putIfAbsent(entry.key, () => entry)..value = value);
- }
-
- /**
- * Removes the LRU position, shifting the linked list if necessary.
- */
- void _removeLru() {
- // Remove the tail from the internal map.
- _entries.remove(_tail.key);
-
- // Remove the tail element itself.
- _tail = _tail.previous;
- _tail.next = null;
- }
-}
« no previous file with comments | « quiver/lib/src/collection/delegates/set.dart ('k') | quiver/lib/src/collection/multimap.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698