/* gnu.classpath.tools.gjdoc.TemporaryStore
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
package gnu.classpath.tools.gjdoc;
/**
* Useful for passing big objects that are no longer needed by the
* calling method, reducing memory usage. <p/>
*
* Consider the following problem:
* <pre>
* public class A {
* public static void foo() {
* long[] hugeArray = new long[1000000]; // takes around 8 MB
* // ... fill hugeArray with some information ...
* bar(hugeArray);
* // ... hugeArray is no more required at this point
* }
* public static void bar(long[] arr) {
* // ... process contents of arr ...
* arr = null;
* System.gc(); // NOTE: will not collect arr!
* // ... do something memory-intensive where arr is not needed
* }
* }
* </pre>
*
* In method <code>bar()</code>, the array cannot be garbage
* collected because the local variable <code>hugeArray</code> in
* method <code>foo()</code> still holds a reference to the array.
* <p/>
*
* When calling <code>bar(new long[1000000]);</code> in
* <code>arr</code> the array <i>can</i> be collected in
* <code>bar()</code>, but that way it can't be initialized in
* <code>foo()</code>. A local variable is needed for
* initialization, but the variable can't be cleared before it is
* passed to <code>bar()</code>! <p/>
*
* <code>TemporaryStore</code> is the solution for this
* dilemma. The modified method <code>foo()</code> which uses a
* <code>TemporaryStore</code> object would look like this:
*
* <pre>
* public static void foo() {
* long[] hugeArray = new long[1000000]; // takes around 7 MB
* // ... fill hugeArray with some very important information ...
* TemporaryStore tstore = new TemporaryStore(hugeArray);
* hugeArray = null;
* bar((long[])tstore.getAndClear());
* }
* </pre>
*
* When control flow is transferred to <code>bar()</code>,
* <code>foo()</code> will hold no more references to the array
* and so it can be garbage collected in <code>bar()</code>.
*
*/
public class TemporaryStore {
private Object storedObject;
/**
* Temporarily store the given object for passing it to a
* different method. <p/>
*
* The method constructing a new TemporaryStore object should
* clear all other references to the stored object, so that
* this TemporaryStore is the only object referencing it.
*
* @param storedObject the object to store temporarily
*
*/
public TemporaryStore(Object storedObject) {
this.storedObject = storedObject;
}
/**
* Return the stored object after clearing the reference to it.
* <p/>
*
* When the user of this class followed the recommendations in
* the documentation of @link{TemporaryStore(Object)}, the
* returned reference will be the only reference to the stored
* object after this method returns. If the returned reference
* is passed in a method call, the called method will hold the
* only reference to the stored object and can release it by
* nulling the corresponding parameter.
*
* @return the object which was passed to the constructor.
*
*/
public Object getAndClear() {
Object rc = this.storedObject;
this.storedObject = null;
return rc;
}
}