blob: 0401cb7c52c78d4a7a4daf190c6fe3a89494a759 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.common.internal.emfworkbench;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.eclipse.wst.common.internal.emfworkbench.integration.EditModel;
/**
* This class will be used to cache the recently used edit models. Loading and unloading of edit models can be
* costly, especially if operations and/or post operations have a need to reload the same edit model repeatedly.
* This will allow those repeatedly used edit models to be cached, thereby improving performance. By design, the
* edit models load resources and these resources are stored in memory, so we don't want to cache every edit
* model accessed, so this is a least used cache mechanism, where the max size is 10. If an edit model is used
* it is put to the back of the stack, and new edit models accessed are put to the back of the stack, so that the
* top of the stack is the first edit model disposed when the cache is higher than the threshhold.
*
*/
public class EditModelLeastUsedCache {
/**
* Provide a singleton instance.
*/
private static EditModelLeastUsedCache INSTANCE = new EditModelLeastUsedCache();
/**
* The threshold, or most edit models we will keep open at a time is 10. This is low enough to not
* overwhelm workbench memory and high enough to aid in operations which continually reload 3-4
* edit models.
*/
private final static int threshhold = 10;
/**
* A LHS is required to ensure the order of the items is maintained. Other
* Set implementations (HashSet, TreeSet) do not preserve the order. This
* is critical to the implementation. DO NOT CHANGE THIS.
*/
private LinkedHashSet lru = new LinkedHashSet(threshhold);
/**
* Accessor for the EditModelLeastUsedCache INSTANCE
*
* @return the EditModelLeastUsedCache INSTANCE
*/
public static EditModelLeastUsedCache getInstance() {
return INSTANCE;
}
/**
* Remove the all elements from the lru that are contained
* in <code>aCollection</code>. This method assumes the
* EditModels in the aCollection will be discarded and it
* will not attempt to decrememt its reference count.
* @param aCollection - A {@link Collection} of {@link EditModel}.
*/
public void removeAllCached(Collection aCollection) {
if (aCollection != null) {
lru.removeAll(aCollection);
}
}
/**
* An {@link EditModel} is being accessed so we will want
* to update the lru and access the editModel which will hold
* a reference count.
* @param editModel - The {@link EditModel} that we want to place
* in the least used cache.
*/
public void access(EditModel editModel) {
boolean shouldAccess = true;
synchronized (lru) {
if (lru.contains(editModel)) {
moveToEnd(editModel);
shouldAccess = false;
}
}
if (shouldAccess) {
editModel.access(this);
synchronized (lru) {
lru.add(editModel);
}
}
}
/**
* If we hit the capacity of the lru then remove the first one
* and release access.
*/
public void optimizeLRUSizeIfNecessary() {
EditModel model = null;
synchronized (lru) {
if (lru.size() > threshhold) {
// remove oldest element and release the edit model.
Iterator iterator = lru.iterator();
model = (EditModel) iterator.next();
if (model != null) {
lru.remove(model);
}
}
}
if (model != null)
model.releaseAccess(this);
}
/**
* Move the editModel to the end of the list
* @param editModel -- EditModel to be moved
*/
private void moveToEnd(EditModel editModel) {
lru.remove(editModel);
lru.add(editModel);
}
}