001: /*
002: * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.java2d;
027:
028: /**
029: * This interface is implemented by classes which contain complex state
030: * so that other objects can track whether or not their state has changed
031: * since earlier interactions with the object.
032: * <p>
033: * The suggested usage pattern for code that manages some trackable data
034: * is as follows:
035: * <pre>
036: * class Trackable implements StateTrackable {
037: * TrackedInfo data;
038: * State curState = STABLE;
039: * StateTracker curTracker = null;
040: * // Hypothetical method to return a static piece of our tracked data.
041: * // Assume that Datum is either a copy of some piece of the tracked
042: * // data or that it is itself immutable.
043: * public Datum getSomeDatum(int key) {
044: * // No need to modify the state for this type of "get" call.
045: * return data.getDatum(key);
046: * }
047: * // Hypothetical method to return a raw reference to our tracked data.
048: * public TrackedInfo getRawHandleToInfo() {
049: * // Since we are returning a raw reference to our tracked
050: * // data and since we can not track what the caller will
051: * // do with that reference, we can no longer track the
052: * // state of this data.
053: * synchronized (this) {
054: * // Note: modifying both curState and curTracker requires
055: * // synchronization against the getStateTracker method.
056: * curState = UNTRACKABLE;
057: * curTracker = null;
058: * }
059: * return data;
060: * }
061: * // Hypothetical method to set a single piece of data to some
062: * // new static value.
063: * public void setSomeDatum(int key, Datum datum) {
064: * data.setDatum(key, datum);
065: * // We do not need to change state for this, we simply
066: * // invalidate the outstanding StateTracker objects.
067: * // Note: setting curTracker to null requires no synchronization.
068: * curTracker = null;
069: * }
070: * // getStateTracker must be synchronized against any code that
071: * // changes the State.
072: * public synchronized StateTracker getStateTracker() {
073: * StateTracker st = curTracker;
074: * if (st == null) {
075: * switch (curState) {
076: * case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break;
077: * case STABLE: st = new Tracker(this); break;
078: * case DYNAMIC: st = StateTracker.NEVER_CURRENT; break;
079: * case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break;
080: * }
081: * curTracker = st;
082: * }
083: * return st;
084: * }
085: *
086: * static class Tracker implements StateTracker {
087: * Trackable theTrackable;
088: * public Tracker(Trackable t) {
089: * theTrackable = t;
090: * }
091: * public boolean isCurrent() {
092: * return (theTrackable.curTracker == this);
093: * }
094: * }
095: * }
096: * </pre>
097: * Note that the mechanism shown above for invalidating outstanding
098: * StateTracker objects is not the most theoretically conservative
099: * way to implement state tracking in a "set" method.
100: * There is a small window of opportunity after the data has changed
101: * before the outstanding StateTracker objects are invalidated and
102: * where they will indicate that the data is still the same as when
103: * they were instantiated.
104: * While this is technically inaccurate, it is acceptable since the more
105: * conservative approaches to state management are much more complex and
106: * cost much more in terms of performance for a very small gain in
107: * correctness.
108: * For example:
109: * <p>
110: * The most conservative approach would be to synchronize all accesses
111: * and all modifications to the data, including its State.
112: * This would require synchronized blocks around some potentially large
113: * bodies of code which would impact the multi-threaded scalability of
114: * the implementation.
115: * Further, if data is to be coordinated or transferred between two
116: * trackable objects then both would need to be synchronized raising
117: * the possibility of deadlock unless some strict rules of priority
118: * for the locking of the objects were established and followed
119: * religiously.
120: * Either or both of these drawbacks makes such an implementation
121: * infeasible.
122: * <p>
123: * A less conservative approach would be to change the state of the
124: * trackable object to DYNAMIC during all modifications of the data
125: * and then to change it back to STABLE after those modifications
126: * are complete.
127: * While this state transition more accurately reflects the temporary
128: * loss of tracking during the modification phase, in reality the
129: * time period of the modifications would be small in most cases
130: * and the 2 changes of state would each require synchronization.
131: * <p>
132: * In comparison the act of setting the <code>curTracker</code>
133: * reference to null in the usage pattern above effectively invalidates
134: * all outstanding <code>Tracker</code> objects as soon as possible
135: * after the change to the data and requires very little code and no
136: * synchronization to implement.
137: * <p>
138: * In the end it is up to the implementor of a StateTrackable object
139: * how fine the granularity of State updates should be managed based
140: * on the frequency and atomicity of the modifications and the
141: * consequences of returning an inaccurate State for a particularly
142: * small window of opportunity.
143: * Most implementations are likely to follow the liberal, but efficient
144: * guidelines found in the usage pattern proposed above.
145: *
146: * @since 1.7
147: */
148: public interface StateTrackable {
149: /**
150: * An enumeration describing the current state of a trackable
151: * object.
152: * These values describe how often the complex data contained
153: * in a trackable object can be changed and whether or not it
154: * makes sense to try to track the data in its current state.
155: * @see StateTrackable#getState
156: * @since 1.7
157: */
158: public enum State {
159: /**
160: * The complex data will never change again.
161: * Information related to the current contents of the complex
162: * data can be calculated and cached indefinitely with no
163: * further checks to see if the information is stale.
164: */
165: IMMUTABLE,
166:
167: /**
168: * The complex data is currently stable, but could change at
169: * some point in the future.
170: * Information related to the current contents of the complex
171: * data can be calculated and cached, but a StateTracker should
172: * be used to verify the freshness of such precalculated data
173: * before each future use.
174: */
175: STABLE,
176:
177: /**
178: * The complex data is currently in flux and is frequently
179: * changing.
180: * While information related to the current contents of the
181: * complex data could be calculated and cached, there is a
182: * reasonably high probability that the cached information
183: * would be found to be out of date by the next time it is
184: * used.
185: * It may also be the case that the current contents are
186: * temporarily untrackable, but that they may become trackable
187: * again in the future.
188: */
189: DYNAMIC,
190:
191: /**
192: * The complex data can currently be changed by external
193: * references and agents in a way that cannot be tracked.
194: * If any information about the current contents of the complex
195: * data were to be cached, there would be no way to determine
196: * whether or not that cached information was out of date.
197: */
198: UNTRACKABLE,
199: };
200:
201: /**
202: * Returns the general state of the complex data held by this
203: * object.
204: * This return value can be used to determine if it makes
205: * strategic sense to try and cache information about the current
206: * contents of this object.
207: * The StateTracker returned from the getStateTracker() method
208: * will further aid in determining when the data has been
209: * changed so that the caches can be verified upon future uses.
210: * @return the current state of trackability of the complex
211: * data stored in this object.
212: * @see #getStateTracker
213: * @since 1.7
214: */
215: public State getState();
216:
217: /**
218: * Returns an object which can track future changes to the
219: * complex data stored in this object.
220: * If an external agent caches information about the complex
221: * data of this object, it should first get a StateTracker
222: * object from this method so that it can check if such
223: * information is current upon future uses.
224: * Note that a valid StateTracker will always be returned
225: * regardless of the return value of getState(), but in some
226: * cases the StateTracker may be a trivial implementation
227: * which always returns the same value from its
228: * {@link StateTracker#isCurrent isCurrent} method.
229: * <ul>
230: * <li>If the current state is {@link State#IMMUTABLE IMMUTABLE},
231: * this StateTracker and any future StateTracker objects
232: * returned from this method will always indicate that
233: * the state has not changed.</li>
234: * <li>If the current state is {@link State#UNTRACKABLE UNTRACKABLE},
235: * this StateTracker and any future StateTracker objects
236: * returned from this method will always indicate that
237: * the state has changed.</li>
238: * <li>If the current state is {@link State#DYNAMIC DYNAMIC},
239: * this StateTracker may always indicate that the current
240: * state has changed, but another StateTracker returned
241: * from this method in the future when the state has changed
242: * to {@link State#STABLE STABLE} will correctly track changes.</li>
243: * <li>Otherwise the current state is {@link State#STABLE STABLE}
244: * and this StateTracker will indicate whether or not the
245: * data has changed since the time at which it was fetched
246: * from the object.</li>
247: * </ul>
248: * @return an object implementing the StateTracker interface
249: * that tracks whether changes have been made to the complex
250: * contents of this object since it was returned.
251: * @see State
252: * @see #getState
253: * @since 1.7
254: */
255: public StateTracker getStateTracker();
256: }
|