linuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacos
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
7.3 KiB
235 lines
7.3 KiB
/** |
|
* This class is used to manage simple, LRU caches. It provides an absolutely minimal |
|
* container interface. It is created like this: |
|
* |
|
* this.itemCache = new Ext.util.Cache({ |
|
* miss: function (key) { |
|
* return new CacheItem(key); |
|
* } |
|
* }); |
|
* |
|
* The `{@link #miss}` abstract method must be implemented by either a derived class or |
|
* at the instance level as shown above. |
|
* |
|
* Once the cache exists and it can handle cache misses, the cache is used like so: |
|
* |
|
* var item = this.itemCache.get(key); |
|
* |
|
* The `key` is some value that uniquely identifies the cached item. |
|
* |
|
* In some cases, creating the cache item may require more than just the lookup key. In |
|
* that case, any extra arguments passed to `get` will be passed to `miss`. |
|
* |
|
* this.otherCache = new Ext.util.Cache({ |
|
* miss: function (key, extra) { |
|
* return new CacheItem(key, extra); |
|
* } |
|
* }); |
|
* |
|
* var item = this.otherCache.get(key, extra); |
|
* |
|
* To process items as they are removed, you can provide an `{@link #evict}` method. The |
|
* stock method is `Ext.emptyFn` and so does nothing. |
|
* |
|
* For example: |
|
* |
|
* this.itemCache = new Ext.util.Cache({ |
|
* miss: function (key) { |
|
* return new CacheItem(key); |
|
* }, |
|
* |
|
* evict: function (key, cacheItem) { |
|
* cacheItem.destroy(); |
|
* } |
|
* }); |
|
* |
|
* @class Ext.util.Cache |
|
* @private |
|
* @since 5.1.0 |
|
*/ |
|
(function (Cache, prototype) { |
|
// @define Ext.util.Cache |
|
|
|
// NOTE: We have to implement this class old-school because it is used by the |
|
// platformConfig class processor (so Ext.define is not yet ready for action). |
|
(Ext.util || (Ext.util = {})).Cache = Cache = function (config) { |
|
var me = this, |
|
head; |
|
|
|
if (config) { |
|
Ext.apply(me, config); |
|
} |
|
|
|
// Give all entries the same object shape. |
|
me.head = head = { |
|
//<debug> |
|
id: (me.seed = 0), |
|
//</debug> |
|
key: null, |
|
value: null |
|
}; |
|
|
|
me.map = {}; |
|
|
|
head.next = head.prev = head; |
|
}; |
|
|
|
Cache.prototype = prototype = { |
|
/** |
|
* @cfg {Number} maxSize The maximum size the cache is allowed to grow to before |
|
* further additions cause removal of the least recently used entry. |
|
*/ |
|
maxSize: 100, |
|
|
|
/** |
|
* @property {Number} count |
|
* The number of items in this cache. |
|
* @readonly |
|
*/ |
|
count: 0, |
|
|
|
/** |
|
* This method is called by `{@link #get}` when the key is not found in the cache. |
|
* The implementation of this method should create the (expensive) value and return |
|
* it. Whatever arguments were passed to `{@link #get}` will be passed on to this |
|
* method. |
|
* |
|
* @param {String} key The cache lookup key for the item. |
|
* @param {Object...} args Any other arguments originally passed to `{@link #get}`. |
|
* @method miss |
|
* @abstract |
|
* @protected |
|
*/ |
|
|
|
/** |
|
* Removes all items from this cache. |
|
*/ |
|
clear: function () { |
|
var me = this, |
|
head = me.head, |
|
entry = head.next; |
|
|
|
head.next = head.prev = head; |
|
|
|
if (!me.evict.$nullFn) { |
|
for ( ; entry !== head; entry = entry.next) { |
|
me.evict(entry.key, entry.value); |
|
} |
|
} |
|
|
|
me.count = 0; |
|
}, |
|
|
|
/** |
|
* Calls the given function `fn` for each item in the cache. The items will be passed |
|
* to `fn` from most-to-least recently used. |
|
* @param {Function} fn The function to call for each cache item. |
|
* @param {String} fn.key The cache key for the item. |
|
* @param {Object} fn.value The value in the cache for the item. |
|
* @param {Object} [scope] The `this` pointer to use for `fn`. |
|
*/ |
|
each: function (fn, scope) { |
|
scope = scope || this; |
|
|
|
for (var head = this.head, ent = head.next; ent !== head; ent = ent.next) { |
|
if (fn.call(scope, ent.key, ent.value)) { |
|
break; |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* Finds an item in this cache and returns its value. If the item is present, it is |
|
* shuffled into the MRU (most-recently-used) position as necessary. If the item is |
|
* missing, the `{@link #miss}` method is called to create the item. |
|
* |
|
* @param {String} key The cache key of the item. |
|
* @param {Object...} args Arguments for the `miss` method should it be needed. |
|
* @return {Object} The cached object. |
|
*/ |
|
get: function (key) { |
|
var me = this, |
|
head = me.head, |
|
map = me.map, |
|
entry = map[key]; |
|
|
|
if (entry) { |
|
if (entry.prev !== head) { |
|
// The entry is not at the front, so remove it and insert it at the front |
|
// (to make it the MRU - Most Recently Used). |
|
me.unlinkEntry(entry); |
|
me.linkEntry(entry); |
|
} |
|
} else { |
|
map[key] = entry = { |
|
//<debug> |
|
id: ++me.seed, |
|
//</debug> |
|
key: key, |
|
value: me.miss.apply(me, arguments) |
|
}; |
|
|
|
me.linkEntry(entry); |
|
++me.count; |
|
|
|
while (me.count > me.maxSize) { |
|
me.unlinkEntry(head.prev, true); |
|
--me.count; |
|
} |
|
} |
|
|
|
return entry.value; |
|
}, |
|
|
|
//------------------------------------------------------------------------- |
|
// Internals |
|
|
|
/** |
|
* This method is called internally from `{@link #get}` when the cache is full and |
|
* the least-recently-used (LRU) item has been removed. |
|
* |
|
* @param {String} key The cache lookup key for the item being removed. |
|
* @param {Object} value The cache value (returned by `{@link #miss}`) for the item |
|
* being removed. |
|
* @method evict |
|
* @template |
|
* @protected |
|
*/ |
|
evict: Ext.emptyFn, |
|
|
|
/** |
|
* Inserts the given entry at the front (MRU) end of the entry list. |
|
* @param {Object} entry The cache item entry. |
|
* @private |
|
*/ |
|
linkEntry: function (entry) { |
|
var head = this.head, |
|
first = head.next; |
|
|
|
entry.next = first; |
|
entry.prev = head; |
|
head.next = entry; |
|
first.prev = entry; |
|
}, |
|
|
|
/** |
|
* Removes the given entry from the entry list. |
|
* @param {Object} entry The cache item entry. |
|
* @param {Boolean} evicted Pass `true` if `{@link #evict}` should be called. |
|
* @private |
|
*/ |
|
unlinkEntry: function (entry, evicted) { |
|
var next = entry.next, |
|
prev = entry.prev; |
|
|
|
prev.next = next; |
|
next.prev = prev; |
|
|
|
if (evicted) { |
|
this.evict(entry.key, entry.value); |
|
} |
|
} |
|
}; |
|
|
|
prototype.destroy = prototype.clear; |
|
}());
|
|
|