001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.texteditor.quickdiff.compare.rangedifferencer;
011:
012: /**
013: * Memory-monitoring factory for <code>LinkedRangeDifference</code>.
014: *
015: * @since 3.0
016: */
017: public class LinkedRangeFactory {
018:
019: /**
020: * Exception that is thrown after the minimal allowed free memory is reached.
021: * <p>
022: * This class is not intended to be serialized.
023: * </p>
024: *
025: */
026: public static class LowMemoryException extends Exception {
027:
028: /**
029: * Serial version UID for this class.
030: * <p>
031: * Note: This class is not intended to be serialized.
032: * </p>
033: * @since 3.1
034: */
035: private static final long serialVersionUID = 3977582493823939894L;
036:
037: /**
038: * Initialize without detail message.
039: */
040: public LowMemoryException() {
041: super ();
042: }
043:
044: /**
045: * Initialize with the given detail message.
046: *
047: * @param message the detail message
048: */
049: public LowMemoryException(String message) {
050: super (message);
051: }
052: }
053:
054: /**
055: * Relative amount of memory that must be free in order to allow the creation of additional instances
056: */
057: private static final double THRESHOLD = 0.1;
058: /**
059: * Number of instantiations after which the amount of free memory is checked
060: */
061: private static final long CHECK_INTERVAL = 5000;
062: /**
063: * Considered maximal size of a difference object in bytes.
064: */
065: private static final long OBJECT_SIZE = 100;
066: /**
067: * The maximal memory requirement for the next round in bytes.
068: */
069: private static final long MAXIMAL_INTERVAL_REQUIREMENT = CHECK_INTERVAL
070: * OBJECT_SIZE;
071: /**
072: * Allowed memory consumption in bytes.
073: */
074: private static final long MAX_MEMORY_CONSUMPTION = 10 * 1024 * 1024;
075: /**
076: * The maximal number of instances.
077: */
078: private static final long MAX_INSTANCES = MAX_MEMORY_CONSUMPTION
079: / OBJECT_SIZE;
080:
081: /**
082: * Preallocated low memory exception
083: */
084: private LowMemoryException fLowMemoryException = new LowMemoryException();
085:
086: /**
087: * Number of instantiations
088: */
089: private long fCount = 0;
090:
091: /**
092: * Create a new linked range difference with the given next range and operation.
093: *
094: * @param next the next linked range difference
095: * @param operation the operation
096: * @return the new linked range difference
097: * @throws LowMemoryException
098: */
099: public LinkedRangeDifference newRange(LinkedRangeDifference next,
100: int operation) throws LowMemoryException {
101: check();
102: return new LinkedRangeDifference(next, operation);
103: }
104:
105: /**
106: * After <code>CHECK_INTERVAL</code> calls check whether at least a fraction of <code>THRESHOLD</code>
107: * of the maximal available memory is free, otherwise throw an {@link LowMemoryException}.
108: *
109: * @throws LowMemoryException
110: */
111: private void check() throws LowMemoryException {
112: if (fCount % CHECK_INTERVAL == 0) {
113:
114: Runtime runtime = Runtime.getRuntime();
115: long maxMemory = runtime.maxMemory();
116: long maxFreeMemory = maxMemory
117: - (runtime.totalMemory() - runtime.freeMemory());
118:
119: if (((float) (maxFreeMemory - MAXIMAL_INTERVAL_REQUIREMENT))
120: / maxMemory < THRESHOLD)
121: throw fLowMemoryException;
122: }
123: if (++fCount >= MAX_INSTANCES)
124: throw fLowMemoryException;
125: }
126: }
|