qcache
Version:
useful caches: ttl, lru, multi-value
109 lines (90 loc) • 2.56 kB
JavaScript
/**
* multi-valued mru/lru (most/least recently used) cache
*
* Copyright (C) 2015-2016,2019 Andras Radics
* Licensed under the Apache License, Version 2.0
*
* 2015-01-18 - AR.
*/
'use strict';
module.exports = MultiValueCache;
function MultiValueCache( ) {
this._lists = {};
this._deleted = {};
this._deletedCount = 0;
}
MultiValueCache.prototype = {
_lists: null,
isEmpty:
function isEmpty( name ) {
return !this._lists[name] || !this._lists[name].length;
},
push:
function push( name, value ) {
var list = this._lists[name] || (this._lists[name] = new Array());
list.push(value);
},
pop:
function pop( name, oldest ) {
var ret, list = this._lists[name];
if (list) {
ret = oldest ? list.shift() : list.pop();
if (!list.length) this._delayedDelete(name);
return ret;
}
return undefined;
},
unshift:
function unshift( name, value ) {
var list = this._lists[name] || (this._lists[name] = new Array());
list.unshift(value);
},
shift:
function shift( name ) {
return this.pop(name, true);
},
set:
function set( name, value ) {
return this.push(name, value);
},
get:
function get( name ) {
return this.pop(name, true);
},
getLength:
function getLength( name ) {
return this._lists[name] ? this._lists[name].length : 0;
},
remove:
function remove( name, item ) {
var idx, list = this._lists[name];
if (list && (idx = list.indexOf(item)) >= 0) {
list.splice(idx, 1);
}
},
keys:
function keys( ) {
return Object.keys(this._lists);
},
_deleted: null,
_deletedCount: 0,
_delayedDelete:
function _delayedDelete( name ) {
// NOTE: a simplistic delete is 87% of the runtime! (11 vs 83 ms)
//if (this._lists[name] && this._lists[name].length < 1) delete this._lists[name];
//return;
// delay the delete, to avoid on/off/on oscillation (17ms)
var lists = this._lists;
lists[name] = undefined;
if (!this._deleted[name]) {
this._deleted[name] = true;
if (++this._deletedCount >= 40) {
for (name in this._deleted) {
if (lists[name] === undefined) delete lists[name];
}
this._deleted = {};
this._deletedCount = 0;
}
}
},
};