iconCache: don't add an icon multiple times and remove it on destruction
When we re-add an icon to the cache we only have to renew its lifetime
without the need of doing anything else.
Also an icon might be destroyed while it's still in cache, in that case
we have to remove it from the cache during destruction (avoiding signal
loops).
Marco Trevisan (TreviƱo)
6 years ago
26 | 26 | // If the lifetime of an icon is over, the cache will destroy the icon. (!) |
27 | 27 | // The presence of an inUse property set to true on the icon will extend the lifetime. |
28 | 28 | |
29 | const LIFETIME_TIMESPAN = 5000; // milli-seconds | |
30 | const GC_INTERVAL = 10000; // milli-seconds | |
31 | ||
29 | 32 | // how to use: see IconCache.add, IconCache.get |
30 | 33 | var IconCache = new Lang.Class({ |
31 | 34 | Name: 'IconCache', |
32 | 35 | |
33 | LIFETIME_TIMESPAN: 5000, //5s | |
34 | GC_INTERVAL: 10000, //10s | |
35 | ||
36 | 36 | _init: function() { |
37 | 37 | this._cache = {}; |
38 | 38 | this._lifetime = {}; //we don't want to attach lifetime to the object |
39 | this._destroyNotify = {}; | |
39 | 40 | this._gc(); |
40 | 41 | }, |
41 | 42 | |
42 | 43 | add: function(id, o) { |
43 | //Util.Logger.debug("IconCache: adding "+id); | |
44 | if (!(o && id)) return null; | |
45 | if (id in this._cache && this._cache[id] !== o) | |
44 | if (!(o && id)) | |
45 | return null; | |
46 | ||
47 | if (!(id in this._cache) || this._cache[id] !== o) { | |
46 | 48 | this._remove(id); |
47 | this._cache[id] = o; | |
48 | this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN; | |
49 | ||
50 | //Util.Logger.debug("IconCache: adding "+id,o); | |
51 | this._cache[id] = o; | |
52 | ||
53 | if (typeof this._cache[id].destroy === 'function') { | |
54 | this._destroyNotify[id] = o.connect('destroy', () => { | |
55 | this._remove(id); | |
56 | }); | |
57 | } | |
58 | } | |
59 | ||
60 | this._renewLifetime(id); | |
61 | ||
49 | 62 | return o; |
50 | 63 | }, |
51 | 64 | |
52 | 65 | _remove: function(id) { |
66 | if (!(id in this._cache)) | |
67 | return; | |
68 | ||
53 | 69 | //Util.Logger.debug('IconCache: removing '+id); |
54 | if ('destroy' in this._cache[id]) this._cache[id].destroy(); | |
70 | ||
71 | if (typeof this._cache[id].destroy === 'function') { | |
72 | this._cache[id].disconnect(this._destroyNotify[id]); | |
73 | this._cache[id].destroy(); | |
74 | } | |
75 | ||
55 | 76 | delete this._cache[id]; |
56 | 77 | delete this._lifetime[id]; |
78 | delete this._destroyNotify[id]; | |
79 | }, | |
80 | ||
81 | _renewLifetime: function(id) { | |
82 | if (id in this._cache) | |
83 | this._lifetime[id] = new Date().getTime() + LIFETIME_TIMESPAN; | |
57 | 84 | }, |
58 | 85 | |
59 | 86 | forceDestroy: function(id) { |
70 | 97 | get: function(id) { |
71 | 98 | if (id in this._cache) { |
72 | 99 | //Util.Logger.debug('IconCache: retrieving '+id); |
73 | this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN; //renew lifetime | |
100 | this._renewLifetime(id); | |
74 | 101 | return this._cache[id]; |
75 | 102 | } |
76 | else return null; | |
103 | ||
104 | return null; | |
77 | 105 | }, |
78 | 106 | |
79 | 107 | _gc: function() { |
80 | 108 | var time = new Date().getTime(); |
81 | 109 | for (var id in this._cache) { |
82 | 110 | if (this._cache[id].inUse) { |
83 | //Util.Logger.debug ("IconCache: " + id + " is in use."); | |
111 | //Util.Logger.debug("IconCache: " + id + " is in use."); | |
84 | 112 | continue; |
85 | 113 | } else if (this._lifetime[id] < time) { |
86 | 114 | this._remove(id); |