From 06ea9c3a8be5effa530fff8de27b9e49f7593040 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 13 Mar 2018 14:50:56 -0400 Subject: [PATCH] lru_cache: support multiple values with the same key --- src/util/lru_cache.js | 41 ++++++++++++++++---------------- test/unit/util/lru_cache.test.js | 4 +++- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/util/lru_cache.js b/src/util/lru_cache.js index 3074c4b5699..e82e7056e31 100644 --- a/src/util/lru_cache.js +++ b/src/util/lru_cache.js @@ -9,7 +9,7 @@ */ class LRUCache { max: number; - data: {[key: string]: T}; + data: {[key: string]: Array}; order: Array; onRemove: (element: T) => void; /** @@ -30,7 +30,9 @@ class LRUCache { */ reset() { for (const key in this.data) { - this.onRemove(this.data[key]); + for (const removedData of this.data[key]) { + this.onRemove(removedData); + } } this.data = {}; @@ -50,20 +52,15 @@ class LRUCache { * @private */ add(key: string, data: T) { + if (this.data[key] === undefined) { + this.data[key] = []; + } + this.data[key].push(data); + this.order.push(key); - if (this.has(key)) { - this.order.splice(this.order.indexOf(key), 1); - this.data[key] = data; - this.order.push(key); - - } else { - this.data[key] = data; - this.order.push(key); - - if (this.order.length > this.max) { - const removedData = this.getAndRemove(this.order[0]); - if (removedData) this.onRemove(removedData); - } + if (this.order.length > this.max) { + const removedData = this.getAndRemove(this.order[0]); + if (removedData) this.onRemove(removedData); } return this; @@ -101,9 +98,11 @@ class LRUCache { getAndRemove(key: string): ?T { if (!this.has(key)) { return null; } - const data = this.data[key]; + const data = this.data[key].shift(); - delete this.data[key]; + if (this.data[key].length === 0) { + delete this.data[key]; + } this.order.splice(this.order.indexOf(key), 1); return data; @@ -120,7 +119,7 @@ class LRUCache { get(key: string): ?T { if (!this.has(key)) { return null; } - const data = this.data[key]; + const data = this.data[key].pop(); return data; } @@ -134,8 +133,10 @@ class LRUCache { remove(key: string) { if (!this.has(key)) { return this; } - const data = this.data[key]; - delete this.data[key]; + const data = this.data[key].pop(); + if (this.data[key].length === 0) { + delete this.data[key]; + } this.onRemove(data); this.order.splice(this.order.indexOf(key), 1); diff --git a/test/unit/util/lru_cache.test.js b/test/unit/util/lru_cache.test.js index c2261812b77..23e03710779 100644 --- a/test/unit/util/lru_cache.test.js +++ b/test/unit/util/lru_cache.test.js @@ -34,7 +34,9 @@ test('LRUCache - duplicate add', (t) => { cache.add('a', 'b'); cache.add('a', 'c'); - t.deepEqual(cache.keys(), ['a']); + t.deepEqual(cache.keys(), ['a', 'a']); + t.ok(cache.has('a')); + t.equal(cache.getAndRemove('a'), 'b'); t.ok(cache.has('a')); t.equal(cache.getAndRemove('a'), 'c'); t.end();