001: /*
002: * EventuallyFreed.java --
003: *
004: * This class makes sure that certain objects
005: * aren't disposed when there are nested procedures that
006: * depend on their existence.
007: *
008: * Copyright (c) 1991-1994 The Regents of the University of California.
009: * Copyright (c) 1994-1998 Sun Microsystems, Inc.
010: * Copyright (c) 2000 Christian Krone.
011: *
012: * See the file "license.terms" for information on usage and redistribution
013: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
014: *
015: * RCS: @(#) $Id: EventuallyFreed.java,v 1.3 2006/08/03 23:24:02 mdejong Exp $
016: */
017:
018: package tcl.lang;
019:
020: abstract class EventuallyFreed {
021:
022: // Number of preserve() calls in effect for this object.
023:
024: int refCount = 0;
025:
026: // True means dispose() was called while a preserve()
027: // call was in effect, so the object must be disposed
028: // when refCount becomes zero.
029:
030: boolean mustFree = false;
031:
032: // Procedure to call to dispose.
033:
034: abstract void eventuallyDispose();
035:
036: // Set to true when tracking down tricky refCount issues
037:
038: final boolean debug = false;
039:
040: /**
041: *----------------------------------------------------------------------
042: *
043: * Tcl_Preserve -> preserve
044: *
045: * This method is used by another method to declare its interest
046: * in this particular object, so that the object will not be
047: * disposed until a matching call to release() has been made.
048: *
049: * Results:
050: * None.
051: *
052: * Side effects:
053: * Information is retained so that the object will
054: * not be disposed until at least the matching call to release().
055: *
056: *----------------------------------------------------------------------
057: */
058:
059: void preserve() {
060: // Just increment its reference count.
061:
062: refCount++;
063:
064: if (debug) {
065: System.out.println("Incremented refCount to " + refCount
066: + " for " + this );
067: }
068: }
069:
070: /*
071: *----------------------------------------------------------------------
072: *
073: * Tcl_Release -> release
074: *
075: * This method is called to cancel a previous call to
076: * preserve(), thereby allowing an object to be
077: * disposed (if no one else cares about it).
078: *
079: * Results:
080: * None.
081: *
082: * Side effects:
083: * If dispose() has been called for this object, and if
084: * no other call to preserve() is still in effect, this object
085: * is disposed.
086: *
087: *----------------------------------------------------------------------
088: */
089:
090: void release() {
091: refCount--;
092:
093: if (debug) {
094: System.out.println("Decremented refCount to " + refCount
095: + " for " + this );
096: }
097:
098: if (refCount == 0) {
099: if (mustFree) {
100: if (debug) {
101: System.out.println("Invoking subclass dispose()");
102: }
103:
104: dispose();
105: }
106: }
107: }
108:
109: /*
110: *----------------------------------------------------------------------
111: *
112: * Tcl_EventuallyFree -> dispose
113: *
114: * Dispose an object, unless a call to preserve() is in
115: * effect for that object. In this case, defer the disposal until
116: * all calls to preserve() have been undone by matching calls to
117: * release().
118: *
119: * Results:
120: * None.
121: *
122: * Side effects:
123: * The object may be disposed by calling eventuallyDispose().
124: *
125: *----------------------------------------------------------------------
126: */
127:
128: public void dispose() {
129: if (debug) {
130: System.out.println("EventuallyFreed.dispose() for " + this );
131: }
132:
133: // See if there is a reference for this pointer. If so, set its
134: // "mustFree" flag (the flag had better not be set already!).
135:
136: if (refCount >= 1) {
137: if (mustFree) {
138: throw new TclRuntimeError(
139: "eventuallyDispose() called twice");
140: }
141: mustFree = true;
142:
143: if (debug) {
144: System.out.println("set mustFree flag for " + this );
145: System.out.println("refCount was " + refCount);
146: }
147:
148: return;
149: }
150:
151: // No reference for this block. Free it now.
152:
153: if (debug) {
154: System.out
155: .println("Invoking EventuallyFreed.eventuallyDispose() for "
156: + this );
157: }
158:
159: eventuallyDispose();
160: }
161:
162: } // end EventuallyFreed
|