123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- class LRUCache {
- constructor() {
- // options
- this.maxSize = 800;
- this.minSize = 600;
- this.unloadPercent = 0.2;
- this.usedSet = new Set();
- this.itemSet = new Set();
- this.itemList = [];
- this.callbacks = new Map();
- }
- // Returns whether or not the cache has reached the maximum size
- isFull() {
- return this.itemSet.size >= this.maxSize;
- }
- add( item, removeCb ) {
- const itemSet = this.itemSet;
- if ( itemSet.has( item ) ) {
- return false;
- }
- if ( this.isFull() ) {
- return false;
- }
- const usedSet = this.usedSet;
- const itemList = this.itemList;
- const callbacks = this.callbacks;
- itemList.push( item );
- usedSet.add( item );
- itemSet.add( item );
- callbacks.set( item, removeCb );
- return true;
- }
- remove( item ) {
- const usedSet = this.usedSet;
- const itemSet = this.itemSet;
- const itemList = this.itemList;
- const callbacks = this.callbacks;
- if ( itemSet.has( item ) ) {
- callbacks.get( item )( item );
- const index = itemList.indexOf( item );
- itemList.splice( index, 1 );
- usedSet.delete( item );
- itemSet.delete( item );
- callbacks.delete( item );
- return true;
- }
- return false;
- }
- markUsed( item ) {
- const itemSet = this.itemSet;
- const usedSet = this.usedSet;
- if ( itemSet.has( item ) && ! usedSet.has( item ) ) {
- const itemList = this.itemList;
- const index = itemList.indexOf( item );
- itemList.splice( index, 1 );
- itemList.push( item );
- usedSet.add( item );
- }
- }
- markAllUnused() {
- this.usedSet.clear();
- }
- unloadUnusedContent( prioritySortCb ) {
- const unloadPercent = this.unloadPercent;
- const targetSize = this.minSize;
- const itemList = this.itemList;
- const itemSet = this.itemSet;
- const usedSet = this.usedSet;
- const callbacks = this.callbacks;
- const unused = itemList.length - usedSet.size;
- if ( itemList.length > targetSize && unused > 0 ) {
- // TODO: sort by priority
- let nodesToUnload = Math.max( itemList.length - targetSize, targetSize ) * unloadPercent;
- nodesToUnload = Math.ceil( nodesToUnload );
- nodesToUnload = Math.min( unused, nodesToUnload );
- const removedItems = itemList.splice( 0, nodesToUnload );
- for ( let i = 0, l = removedItems.length; i < l; i ++ ) {
- const item = removedItems[ i ];
- callbacks.get( item )( item );
- itemSet.delete( item );
- callbacks.delete( item );
- }
- }
- }
- scheduleUnload( prioritySortCb, markAllUnused = true ) {
- if ( ! this.scheduled ) {
- this.scheduled = true;
- Promise.resolve().then( () => {
- this.scheduled = false;
- this.unloadUnusedContent( prioritySortCb );
- if ( markAllUnused ) {
- this.markAllUnused();
- }
- } );
- }
- }
- }
- export { LRUCache };
|