| /******************************************************************************* |
| * 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); |
| } |
| } |