All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.mat.parser.internal.snapshot.ObjectCache Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2008 SAP AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.mat.parser.internal.snapshot;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.mat.collect.HashMapIntObject;

abstract public class ObjectCache {
    static class Entry {
        E object;
        int key;
        int numUsages;
    }

    private int maxSize;
    private final HashMapIntObject> map;
    private final List>> lfus;
    private int maxLfuBuckets = 0;
    private int lowestNonEmptyLfu = 0;

    public ObjectCache(int maxSize) {
        this.maxSize = maxSize;
        this.map = new HashMapIntObject>(maxSize);
        this.lfus = new ArrayList>>(5);
        this.maxLfuBuckets = maxSize / 3;
    }

    public synchronized E get(int objectId) {
        Entry e = map.get(objectId);
        if (e != null) {
            revalueEntry(e);
        } else {
            e = new Entry();
            e.object = load(objectId);
            e.key = objectId;

            doInsert(e);

            while (map.size() > maxSize)
                removeLeastValuableNode();
        }

        return e.object;
    }

    public synchronized void clear() {
        this.map.clear();
        this.lfus.clear();
    }

    protected abstract E load(int key);

    protected synchronized void doInsert(final Entry e) {
        lfu(e.numUsages).addFirst(e);
        Entry p = map.put(e.key, e);
        lowestNonEmptyLfu = 0;

        if (p != null)
            lfu(p.numUsages).remove(p);
    }

    protected final LinkedList> lfu(int numUsageIndex) {
        int lfuIndex = Math.min(maxLfuBuckets, numUsageIndex);

        if (lfuIndex >= lfus.size()) {
            LinkedList> lfu = new LinkedList>();
            lfus.add(lfuIndex, lfu);
            return lfu;
        } else {
            return lfus.get(lfuIndex);
        }
    }

    protected void revalueEntry(Entry entry) {
        LinkedList> currBucket = lfu(entry.numUsages);
        LinkedList> nextBucket = lfu(++entry.numUsages);

        currBucket.remove(entry);
        nextBucket.addFirst(entry);
    }

    protected LinkedList> getLowestNonEmptyLfu() {
        LinkedList> lfu = null;
        for (int i = lowestNonEmptyLfu; i < lfus.size(); i++) {
            lfu = lfu(i);

            if (lfu.size() != 0) {
                lowestNonEmptyLfu = i;
                return lfu;
            }
        }
        return lfu;
    }

    protected void removeLeastValuableNode() {
        LinkedList> lfu = getLowestNonEmptyLfu();
        Entry lln = lfu.remove(lfu.size() - 1);
        map.remove(lln.key);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy