UNPKG

@thermopylae/lib.cache

Version:
105 lines (104 loc) 3.82 kB
import { DoublyLinkedList } from "../../data-structures/list/doubly-linked.js"; import { CircularBuffer } from "../../data-structures/circular-buffer.js"; import { createException } from "../../error.js"; const SEGMENT_TYPE_SYM = Symbol('ARC_SEGMENT_TYPE_SYM'); class ArcEvictionPolicy { segments; deleteFromCache; constructor(cacheMaxCapacity) { if (cacheMaxCapacity < 2) { throw createException("INVALID_CACHE_MAX_CAPACITY" , `Cache maximum capacity needs to be at least 2.`); } this.segments = { [0 ]: { capacity: Math.round(cacheMaxCapacity / 2), block: new DoublyLinkedList(), ghosts: new CircularBuffer(Math.round(cacheMaxCapacity / 2)) }, [1 ]: { capacity: 0, block: new DoublyLinkedList(), ghosts: new CircularBuffer(Math.round(cacheMaxCapacity / 2)) } }; this.segments[1 ].capacity = cacheMaxCapacity - this.segments[0 ].capacity; } onHit(entry) { if (entry[SEGMENT_TYPE_SYM] === 0 ) { if (this.segments[1 ].capacity === 0) { this.segments[0 ].block.toTail(entry); return 1 ; } this.segments[0 ].block.remove(entry); this.insertInT2(entry); return 1 ; } this.segments[1 ].block.toFront(entry); return 1 ; } onMiss(key) { if (this.segments[0 ].ghosts.has(key)) { if (this.segments[1 ].capacity === 0) { return; } this.segments[0 ].capacity += 1; this.segments[1 ].capacity -= 1; if (this.segments[1 ].block.size > this.segments[1 ].capacity) { this.deleteFromCache(this.segments[1 ].block.tail); } return; } if (this.segments[1 ].ghosts.has(key)) { if (this.segments[0 ].capacity === 0) { return; } this.segments[1 ].capacity += 1; this.segments[0 ].capacity -= 1; if (this.segments[0 ].block.size > this.segments[0 ].capacity) { this.deleteFromCache(this.segments[0 ].block.head); } } } onSet(entry) { this.insertInT1(entry); } onUpdate() { return undefined; } onDelete(entry) { this.segments[entry[SEGMENT_TYPE_SYM]].block.remove(entry); this.segments[entry[SEGMENT_TYPE_SYM]].ghosts.add(entry.key); entry[SEGMENT_TYPE_SYM] = undefined; } onClear() { this.segments[0 ].block.clear(); this.segments[0 ].ghosts.clear(); this.segments[1 ].block.clear(); this.segments[1 ].ghosts.clear(); const cacheMaxCapacity = this.segments[0 ].capacity + this.segments[1 ].capacity; this.segments[0 ].capacity = Math.round(cacheMaxCapacity / 2); this.segments[1 ].capacity = cacheMaxCapacity - this.segments[0 ].capacity; } setDeleter(deleter) { this.deleteFromCache = deleter; } insertInT1(entry) { if (this.segments[0 ].capacity === 0) { this.insertInT2(entry); return; } if (this.segments[0 ].block.size === this.segments[0 ].capacity) { this.deleteFromCache(this.segments[0 ].block.head); } entry[SEGMENT_TYPE_SYM] = 0 ; this.segments[0 ].block.push(entry); } insertInT2(entry) { if (this.segments[1 ].block.size === this.segments[1 ].capacity) { this.deleteFromCache(this.segments[1 ].block.tail); } entry[SEGMENT_TYPE_SYM] = 1 ; this.segments[1 ].block.unshift(entry); } } export { ArcEvictionPolicy, SEGMENT_TYPE_SYM };