package.src.core.LRU.ts Maven / Gradle / Ivy
import { Dictionary } from './types';
// Simple LRU cache use doubly linked list
// @module zrender/core/LRU
export class Entry {
value: T
key: string | number
next: Entry
prev: Entry
constructor(val: T) {
this.value = val;
}
}
/**
* Simple double linked list. Compared with array, it has O(1) remove operation.
* @constructor
*/
export class LinkedList {
head: Entry
tail: Entry
private _len = 0
/**
* Insert a new value at the tail
*/
insert(val: T): Entry {
const entry = new Entry(val);
this.insertEntry(entry);
return entry;
}
/**
* Insert an entry at the tail
*/
insertEntry(entry: Entry) {
if (!this.head) {
this.head = this.tail = entry;
}
else {
this.tail.next = entry;
entry.prev = this.tail;
entry.next = null;
this.tail = entry;
}
this._len++;
}
/**
* Remove entry.
*/
remove(entry: Entry) {
const prev = entry.prev;
const next = entry.next;
if (prev) {
prev.next = next;
}
else {
// Is head
this.head = next;
}
if (next) {
next.prev = prev;
}
else {
// Is tail
this.tail = prev;
}
entry.next = entry.prev = null;
this._len--;
}
/**
* Get length
*/
len(): number {
return this._len;
}
/**
* Clear list
*/
clear() {
this.head = this.tail = null;
this._len = 0;
}
}
/**
* LRU Cache
*/
export default class LRU {
private _list = new LinkedList()
private _maxSize = 10
private _lastRemovedEntry: Entry
private _map: Dictionary> = {}
constructor(maxSize: number) {
this._maxSize = maxSize;
}
/**
* @return Removed value
*/
put(key: string | number, value: T): T {
const list = this._list;
const map = this._map;
let removed = null;
if (map[key] == null) {
const len = list.len();
// Reuse last removed entry
let entry = this._lastRemovedEntry;
if (len >= this._maxSize && len > 0) {
// Remove the least recently used
const leastUsedEntry = list.head;
list.remove(leastUsedEntry);
delete map[leastUsedEntry.key];
removed = leastUsedEntry.value;
this._lastRemovedEntry = leastUsedEntry;
}
if (entry) {
entry.value = value;
}
else {
entry = new Entry(value);
}
entry.key = key;
list.insertEntry(entry);
map[key] = entry;
}
return removed;
}
get(key: string | number): T {
const entry = this._map[key];
const list = this._list;
if (entry != null) {
// Put the latest used entry in the tail
if (entry !== list.tail) {
list.remove(entry);
list.insertEntry(entry);
}
return entry.value;
}
}
/**
* Clear the cache
*/
clear() {
this._list.clear();
this._map = {};
}
len() {
return this._list.len();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy