001: /*
002: * $RCSfile: MemoryFreeList.java,v $
003: *
004: * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.6 $
028: * $Date: 2008/02/28 20:17:26 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.*;
035:
036: /**
037: * Class for storing various free lists. This class must be
038: * synchronized because different threads may try to access the lists.
039: */
040: class MemoryFreeList {
041:
042: // never go smaller than the initial capacity
043: ArrayList elementData = null;
044: int size = 0;
045: int currBlockSize = 10;
046: Object[] currBlock = null;
047: int currBlockIndex = 0;
048: int spaceUsed = 0;
049: int numBlocks = 0;
050: int capacity = 0;
051: int minBlockSize = 0;
052: boolean justShrunk = false;
053: int initcap = 10;
054:
055: // the minimum size since the last shrink
056: int minSize = 0;
057:
058: Class c = null;
059:
060: MemoryFreeList(String className) {
061: this (className, 10);
062: }
063:
064: MemoryFreeList(String className, int initialCapacity) {
065: if (initialCapacity < 0) {
066: throw new IllegalArgumentException("Illegal Capacity: "
067: + initialCapacity);
068: }
069:
070: try {
071: c = Class.forName(className);
072: } catch (Exception e) {
073: System.err.println(e);
074: }
075:
076: initcap = initialCapacity;
077: currBlockSize = initialCapacity;
078: minBlockSize = currBlockSize;
079: elementData = new ArrayList();
080: // add the first block of memory to the arraylist
081: currBlock = new Object[currBlockSize];
082: elementData.add(currBlock);
083: numBlocks++;
084: capacity += currBlockSize;
085: }
086:
087: /*
088: MemoryFreeList(String className, Collection collection) {
089: try {
090: c = Class.forName(className);
091: }
092: catch (Exception e) {
093: // System.err.println(e);
094: }
095:
096: size = collection.size();
097: initcap = size;
098: currBlockSize = size;
099: minBlockSize = currBlockSize;
100: elementData = new ArrayList();
101: currBlock = new Object[currBlockSize];
102: collection.toArray(currBlock);
103: elementData.add(currBlock);
104: numBlocks++;
105: capacity += currBlockSize;
106: spaceUsed = size;
107: }
108: */
109:
110: synchronized int size() {
111: return size;
112: }
113:
114: synchronized boolean add(Object o) {
115: if (justShrunk) {
116: // empty some space out in the current block instead of
117: // adding this message
118: if ((currBlockSize / 2) < spaceUsed) {
119: size -= (spaceUsed - (currBlockSize / 2));
120: spaceUsed = (currBlockSize / 2);
121: Arrays.fill(currBlock, spaceUsed, currBlockSize - 1,
122: null);
123: }
124: justShrunk = false;
125: return false;
126: } else {
127: ensureCapacity(size + 1);
128:
129: // check to see if the whole block is used and if so, reset the
130: // current block
131: // System.err.println("spaceUsed = " + spaceUsed + " currBlockSize = " +
132: // currBlockSize + " currBlockIndex = " +
133: // currBlockIndex + " currBlock = " + currBlock);
134: if ((currBlockIndex == -1) || (spaceUsed >= currBlockSize)) {
135: currBlockIndex++;
136: currBlock = (Object[]) elementData.get(currBlockIndex);
137: currBlockSize = currBlock.length;
138: spaceUsed = 0;
139: }
140: int index = spaceUsed++;
141: currBlock[index] = o;
142: size++;
143:
144: return true;
145: }
146: }
147:
148: protected synchronized Object removeLastElement() {
149: // System.err.println("removeLastElement: size = " + size);
150: int index = --spaceUsed;
151: // System.err.println("index = " + index);
152: Object elm = currBlock[index];
153: currBlock[index] = null;
154: size--;
155:
156: // see if this block is empty now, and if it is set the previous
157: // block to the current block
158: if (spaceUsed == 0) {
159: currBlockIndex--;
160: if (currBlockIndex < 0) {
161: currBlock = null;
162: currBlockSize = 0;
163: } else {
164: currBlock = (Object[]) elementData.get(currBlockIndex);
165: currBlockSize = currBlock.length;
166: }
167: spaceUsed = currBlockSize;
168: }
169:
170: return elm;
171: }
172:
173: synchronized void shrink() {
174: // System.err.println("shrink size = " + size + " minSize = " +
175: // minSize);
176: if ((minSize > minBlockSize) && (numBlocks > 1)) {
177: justShrunk = true;
178:
179: // System.err.println("removing a block");
180: // Runtime r = Runtime.getRuntime();
181: // r.gc();
182: // System.err.println("numBlocks = " + numBlocks + " size = " + size);
183: // System.err.println("free memory before shrink: " + r.freeMemory());
184:
185: // remove the last block
186: Object[] block = (Object[]) elementData
187: .remove(numBlocks - 1);
188: numBlocks--;
189: capacity -= block.length;
190:
191: // we only need to do this if the block removed was the current
192: // block. otherwise we just removed a null block.
193: if (numBlocks == currBlockIndex) {
194: size -= spaceUsed;
195: // set the current block to the last one
196: currBlockIndex = numBlocks - 1;
197: currBlock = (Object[]) elementData.get(currBlockIndex);
198: currBlockSize = currBlock.length;
199:
200: spaceUsed = currBlockSize;
201:
202: }
203:
204: // r.gc();
205: // System.err.println("free memory after shrink: " + r.freeMemory());
206: // System.err.println("numBlocks = " + numBlocks + " size = " + size);
207: } else {
208: justShrunk = false;
209: }
210: minSize = size;
211: }
212:
213: synchronized void ensureCapacity(int minCapacity) {
214: // System.err.println("ensureCapacity: size = " + size + " capacity: " +
215: // elementData.length);
216: // System.err.println("minCapacity = " + minCapacity + " capacity = "
217: // + capacity);
218:
219: if (minCapacity > capacity) {
220: // System.err.println("adding a block: numBlocks = " + numBlocks);
221: int lastBlockSize = ((Object[]) elementData
222: .get(numBlocks - 1)).length;
223: int prevBlockSize = 0;
224: if (numBlocks > 1) {
225: prevBlockSize = ((Object[]) elementData
226: .get(numBlocks - 2)).length;
227: }
228: currBlockSize = lastBlockSize + prevBlockSize;
229: currBlock = new Object[currBlockSize];
230: elementData.add(currBlock);
231: numBlocks++;
232: currBlockIndex++;
233: capacity += currBlockSize;
234: // there is nothing used in this block yet
235: spaceUsed = 0;
236: }
237: }
238:
239: synchronized void rangeCheck(int index) {
240: if (index >= size || index < 0) {
241: throw new IndexOutOfBoundsException("Index: " + index
242: + ", Size: " + size);
243: }
244: }
245:
246: public synchronized void clear() {
247: // System.err.println("clear");
248: elementData.clear();
249:
250: // put an empty block in
251: currBlockSize = initcap;
252: minBlockSize = currBlockSize;
253: currBlock = new Object[currBlockSize];
254: elementData.add(currBlock);
255: numBlocks = 1;
256: capacity = currBlockSize;
257: spaceUsed = 0;
258: size = 0;
259: currBlockIndex = 0;
260: justShrunk = false;
261: }
262:
263: synchronized Object getObject() {
264: if (size > 0) {
265: return removeLastElement();
266: } else {
267: try {
268: return c.newInstance();
269: } catch (Exception e) {
270: System.err.println(e);
271: return null;
272: }
273: }
274: }
275:
276: }
|