Codebase list gnome-shell-extension-appindicator / ubuntu/17.10.1 iconCache.js
ubuntu/17.10.1

Tree @ubuntu/17.10.1 (Download .tar.gz)

iconCache.js @ubuntu/17.10.1

e2de1b7
2d2d1f7
 
 
 
 
ef1c3b8
2d2d1f7
 
 
 
 
 
 
 
 
90c376a
 
 
 
2d2d1f7
7e7a328
 
2d2d1f7
 
 
 
 
 
 
1dc5e56
0383431
e2de1b7
0383431
 
e2de1b7
0383431
 
 
 
 
e2de1b7
0383431
7e7a328
0383431
35e3e1c
0383431
 
 
 
 
e2de1b7
0383431
7e7a328
0383431
 
 
 
e2de1b7
0383431
 
 
7e7a328
 
 
 
 
 
e2de1b7
7e7a328
0383431
 
35e3e1c
0383431
 
 
 
 
e2de1b7
0383431
 
 
 
7e7a328
0383431
 
 
 
7e7a328
0383431
 
 
 
 
e2de1b7
0383431
 
35e3e1c
0383431
2d2d1f7
// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

const GLib = imports.gi.GLib

const Lang = imports.lang
const Mainloop = imports.mainloop

const Util = imports.misc.extensionUtils.getCurrentExtension().imports.util;

// The icon cache caches icon objects in case they're reused shortly aftwerwards.
// This is necessary for some indicators like skype which rapidly switch between serveral icons.
// Without caching, the garbage collection would never be able to handle the amount of new icon data.
// If the lifetime of an icon is over, the cache will destroy the icon. (!)
// The presence of an inUse property set to true on the icon will extend the lifetime.

// how to use: see IconCache.add, IconCache.get
var IconCache = new Lang.Class({
    Name: 'IconCache',

    LIFETIME_TIMESPAN: 5000, //5s
    GC_INTERVAL: 10000, //10s

    _init: function() {
        this._cache = {};
        this._lifetime = {}; //we don't want to attach lifetime to the object
        this._gc();
    },

    add: function(id, o) {
        //Util.Logger.debug("IconCache: adding "+id);
        if (!(o && id)) return null;
        if (id in this._cache && this._cache[id] !== o)
            this._remove(id);
        this._cache[id] = o;
        this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN;
        return o;
    },

    _remove: function(id) {
        //Util.Logger.debug('IconCache: removing '+id);
        if ('destroy' in this._cache[id]) this._cache[id].destroy();
        delete this._cache[id];
        delete this._lifetime[id];
    },

    forceDestroy: function(id) {
        this._remove(id);
    },

    // removes everything from the cache
    clear: function() {
        for (let id in this._cache)
            this._remove(id)
    },

    // returns an object from the cache, or null if it can't be found.
    get: function(id) {
        if (id in this._cache) {
            //Util.Logger.debug('IconCache: retrieving '+id);
            this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN; //renew lifetime
            return this._cache[id];
        }
        else return null;
    },

    _gc: function() {
        var time = new Date().getTime();
        for (var id in this._cache) {
            if (this._cache[id].inUse) {
                //Util.Logger.debug ("IconCache: " + id + " is in use.");
                continue;
            } else if (this._lifetime[id] < time) {
                this._remove(id);
            } else {
                //Util.Logger.debug("IconCache: " + id + " survived this round.");
            }
        }
        if (!this._stopGc) Mainloop.timeout_add(this.GC_INTERVAL, Lang.bind(this, this._gc));
        return false; //we just added our timeout again.
    },

    destroy: function() {
        this._stopGc = true;
        this.clear();
    }
});