API Docs for: 1.0.0
Show:

File: src/gallery-mru-cache/js/MRUCache.js

  1. /**
  2. * @module gallery-mru-cache
  3. */
  4.  
  5. /**********************************************************************
  6. * <p>Cache which drops items based on "most recently used." Items are
  7. * dropped when a user-defined criterion is exceeded, e.g., total size or
  8. * number of items.</p>
  9. *
  10. * <p>The items are stored in a map of {data,mru_item_ref}. The MRU items
  11. * are stored in a doubly linked list (which stores the map keys) to allow
  12. * easy re-ordering and dropping of items. Every cache hit moves the
  13. * associated MRU item to the front of the list.</p>
  14. *
  15. * @main gallery-mru-cache
  16. * @class MRUCache
  17. * @constructor
  18. * @param config {Object}
  19. * @param config.metric {Function} Computes the metric for an item. It receives the value as an argument and must return a positive number.
  20. * @param config.limit {Number} Maximum allowed value of the metric. Items are dropped off the end of the MRU list until the metric is less than or equal to the limit.
  21. * @param [config.meta] {Function} Attaches meta data to an item when it is added to the cache. It receives the value as an argument.
  22. * @param [config.stats] {Boolean} Pass true if you want to collect basic statistics. Pass a function if you want to control what information is stored for each key. The function receives the key, the value, and the stat object.
  23. */
  24. function MRUCache(config)
  25. {
  26. this._metric_fn = config.metric;
  27. this._limit = config.limit;
  28. this._meta = config.meta;
  29. this._stats = config.stats ? initStats() : null;
  30.  
  31. if (Y.Lang.isFunction(config.stats))
  32. {
  33. this._stats_key_meta = config.stats;
  34. }
  35.  
  36. this.clear();
  37. }
  38.  
  39. function initStats()
  40. {
  41. return { gets: 0, keys: {} };
  42. }
  43.  
  44. function initKeyStats(keys, key)
  45. {
  46. if (!keys[key])
  47. {
  48. keys[key] = { puts: 0, gets: 0 };
  49. }
  50. }
  51.  
  52. MRUCache.prototype =
  53. {
  54. /**
  55. * Retrieve a value.
  56. *
  57. * @method get
  58. * @param key {String} the key of the object to retrieve
  59. * @return {Mixed} the stored object, or undefined if the slot is empty
  60. */
  61. get: function(
  62. /* string */ key)
  63. {
  64. var obj = this._store[key];
  65. if (obj)
  66. {
  67. this._mru.prepend(obj.mru);
  68.  
  69. if (this._stats)
  70. {
  71. this._stats.gets++;
  72.  
  73. initKeyStats(this._stats.keys, key);
  74. this._stats.keys[key].gets++;
  75. }
  76.  
  77. return obj.data;
  78. }
  79. },
  80.  
  81. /**
  82. * Store a value.
  83. *
  84. * @method put
  85. * @param key {String} the key of the value
  86. * @param value {Object} the value to store
  87. * @return {boolean} false if the key has already been used
  88. */
  89. put: function(
  90. /* string */ key,
  91. /* obj/fn */ value)
  92. {
  93. var exists = !Y.Lang.isUndefined(this._store[key]);
  94. if (exists)
  95. {
  96. return false;
  97. }
  98.  
  99. var obj =
  100. {
  101. data: value,
  102. mru: this._mru.prepend(key)
  103. };
  104.  
  105. if (this._meta)
  106. {
  107. obj.meta = this._meta(value);
  108. }
  109.  
  110. this._store[key] = obj;
  111.  
  112. this._metric += this._metric_fn(value);
  113. while (this._metric > this._limit)
  114. {
  115. this.remove(this._mru.tail().value);
  116. }
  117.  
  118. if (this._stats)
  119. {
  120. initKeyStats(this._stats.keys, key);
  121. this._stats.keys[key].puts++;
  122.  
  123. if (this._stats_key_meta)
  124. {
  125. this._stats_key_meta(key, value, this._stats.keys[key]);
  126. }
  127. }
  128.  
  129. return true;
  130. },
  131.  
  132. /**
  133. * Store a value.
  134. *
  135. * @method replace
  136. * @param key {String} the key of the value
  137. * @param value {Object} the value to store
  138. * @return {Mixed} the original value that was in the slot, or undefined if the slot is empty
  139. */
  140. replace: function(
  141. /* string */ key,
  142. /* obj/fn */ value)
  143. {
  144. var orig = this.remove(key);
  145. this.put(key, value);
  146. return orig;
  147. },
  148.  
  149. /**
  150. * Remove an value.
  151. *
  152. * @method remove
  153. * @param key {String} the key of the value
  154. * @return {mixed} the value that was removed, or undefined if the slot was empty
  155. */
  156. remove: function(
  157. /* string */ key)
  158. {
  159. var orig = this._store[key];
  160. delete this._store[key];
  161. if (orig)
  162. {
  163. this._mru.remove(orig.mru);
  164. this._metric -= this._metric_fn(orig.data);
  165. return orig.data;
  166. }
  167. },
  168.  
  169. /**
  170. * Remove all values.
  171. *
  172. * @method clear
  173. */
  174. clear: function()
  175. {
  176. this._store = {};
  177. this._mru = new Y.LinkedList();
  178. this._metric = 0;
  179. },
  180.  
  181. /**
  182. * This resets all the values.
  183. *
  184. * @method dumpStats
  185. * @return {Object} the current stats
  186. */
  187. dumpStats: function()
  188. {
  189. var stats = this._stats;
  190. this._stats = initStats();
  191. return stats;
  192. }
  193. };
  194.  
  195. Y.MRUCache = MRUCache;
  196.