| /* | |
| * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code 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 | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package sun.java2d; | |
| /** | |
| * This interface is implemented by classes which contain complex state | |
| * so that other objects can track whether or not their state has changed | |
| * since earlier interactions with the object. | |
| * <p> | |
| * The suggested usage pattern for code that manages some trackable data | |
| * is as follows: | |
| * <pre> | |
| * class Trackable implements StateTrackable { | |
| * TrackedInfo data; | |
| * State curState = STABLE; | |
| * StateTracker curTracker = null; | |
| * // Hypothetical method to return a static piece of our tracked data. | |
| * // Assume that Datum is either a copy of some piece of the tracked | |
| * // data or that it is itself immutable. | |
| * public Datum getSomeDatum(int key) { | |
| * // No need to modify the state for this type of "get" call. | |
| * return data.getDatum(key); | |
| * } | |
| * // Hypothetical method to return a raw reference to our tracked data. | |
| * public TrackedInfo getRawHandleToInfo() { | |
| * // Since we are returning a raw reference to our tracked | |
| * // data and since we can not track what the caller will | |
| * // do with that reference, we can no longer track the | |
| * // state of this data. | |
| * synchronized (this) { | |
| * // Note: modifying both curState and curTracker requires | |
| * // synchronization against the getStateTracker method. | |
| * curState = UNTRACKABLE; | |
| * curTracker = null; | |
| * } | |
| * return data; | |
| * } | |
| * // Hypothetical method to set a single piece of data to some | |
| * // new static value. | |
| * public void setSomeDatum(int key, Datum datum) { | |
| * data.setDatum(key, datum); | |
| * // We do not need to change state for this, we simply | |
| * // invalidate the outstanding StateTracker objects. | |
| * // Note: setting curTracker to null requires no synchronization. | |
| * curTracker = null; | |
| * } | |
| * // getStateTracker must be synchronized against any code that | |
| * // changes the State. | |
| * public synchronized StateTracker getStateTracker() { | |
| * StateTracker st = curTracker; | |
| * if (st == null) { | |
| * switch (curState) { | |
| * case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break; | |
| * case STABLE: st = new Tracker(this); break; | |
| * case DYNAMIC: st = StateTracker.NEVER_CURRENT; break; | |
| * case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break; | |
| * } | |
| * curTracker = st; | |
| * } | |
| * return st; | |
| * } | |
| * | |
| * static class Tracker implements StateTracker { | |
| * Trackable theTrackable; | |
| * public Tracker(Trackable t) { | |
| * theTrackable = t; | |
| * } | |
| * public boolean isCurrent() { | |
| * return (theTrackable.curTracker == this); | |
| * } | |
| * } | |
| * } | |
| * </pre> | |
| * Note that the mechanism shown above for invalidating outstanding | |
| * StateTracker objects is not the most theoretically conservative | |
| * way to implement state tracking in a "set" method. | |
| * There is a small window of opportunity after the data has changed | |
| * before the outstanding StateTracker objects are invalidated and | |
| * where they will indicate that the data is still the same as when | |
| * they were instantiated. | |
| * While this is technically inaccurate, it is acceptable since the more | |
| * conservative approaches to state management are much more complex and | |
| * cost much more in terms of performance for a very small gain in | |
| * correctness. | |
| * For example: | |
| * <p> | |
| * The most conservative approach would be to synchronize all accesses | |
| * and all modifications to the data, including its State. | |
| * This would require synchronized blocks around some potentially large | |
| * bodies of code which would impact the multi-threaded scalability of | |
| * the implementation. | |
| * Further, if data is to be coordinated or transferred between two | |
| * trackable objects then both would need to be synchronized raising | |
| * the possibility of deadlock unless some strict rules of priority | |
| * for the locking of the objects were established and followed | |
| * religiously. | |
| * Either or both of these drawbacks makes such an implementation | |
| * infeasible. | |
| * <p> | |
| * A less conservative approach would be to change the state of the | |
| * trackable object to DYNAMIC during all modifications of the data | |
| * and then to change it back to STABLE after those modifications | |
| * are complete. | |
| * While this state transition more accurately reflects the temporary | |
| * loss of tracking during the modification phase, in reality the | |
| * time period of the modifications would be small in most cases | |
| * and the 2 changes of state would each require synchronization. | |
| * <p> | |
| * In comparison the act of setting the {@code curTracker} | |
| * reference to null in the usage pattern above effectively invalidates | |
| * all outstanding {@code Tracker} objects as soon as possible | |
| * after the change to the data and requires very little code and no | |
| * synchronization to implement. | |
| * <p> | |
| * In the end it is up to the implementor of a StateTrackable object | |
| * how fine the granularity of State updates should be managed based | |
| * on the frequency and atomicity of the modifications and the | |
| * consequences of returning an inaccurate State for a particularly | |
| * small window of opportunity. | |
| * Most implementations are likely to follow the liberal, but efficient | |
| * guidelines found in the usage pattern proposed above. | |
| * | |
| * @since 1.7 | |
| */ | |
| public interface StateTrackable { | |
| /** | |
| * An enumeration describing the current state of a trackable | |
| * object. | |
| * These values describe how often the complex data contained | |
| * in a trackable object can be changed and whether or not it | |
| * makes sense to try to track the data in its current state. | |
| * @see StateTrackable#getState | |
| * @since 1.7 | |
| */ | |
| public enum State { | |
| /** | |
| * The complex data will never change again. | |
| * Information related to the current contents of the complex | |
| * data can be calculated and cached indefinitely with no | |
| * further checks to see if the information is stale. | |
| */ | |
| IMMUTABLE, | |
| /** | |
| * The complex data is currently stable, but could change at | |
| * some point in the future. | |
| * Information related to the current contents of the complex | |
| * data can be calculated and cached, but a StateTracker should | |
| * be used to verify the freshness of such precalculated data | |
| * before each future use. | |
| */ | |
| STABLE, | |
| /** | |
| * The complex data is currently in flux and is frequently | |
| * changing. | |
| * While information related to the current contents of the | |
| * complex data could be calculated and cached, there is a | |
| * reasonably high probability that the cached information | |
| * would be found to be out of date by the next time it is | |
| * used. | |
| * It may also be the case that the current contents are | |
| * temporarily untrackable, but that they may become trackable | |
| * again in the future. | |
| */ | |
| DYNAMIC, | |
| /** | |
| * The complex data can currently be changed by external | |
| * references and agents in a way that cannot be tracked. | |
| * If any information about the current contents of the complex | |
| * data were to be cached, there would be no way to determine | |
| * whether or not that cached information was out of date. | |
| */ | |
| UNTRACKABLE, | |
| } | |
| /** | |
| * Returns the general state of the complex data held by this | |
| * object. | |
| * This return value can be used to determine if it makes | |
| * strategic sense to try and cache information about the current | |
| * contents of this object. | |
| * The StateTracker returned from the getStateTracker() method | |
| * will further aid in determining when the data has been | |
| * changed so that the caches can be verified upon future uses. | |
| * @return the current state of trackability of the complex | |
| * data stored in this object. | |
| * @see #getStateTracker | |
| * @since 1.7 | |
| */ | |
| public State getState(); | |
| /** | |
| * Returns an object which can track future changes to the | |
| * complex data stored in this object. | |
| * If an external agent caches information about the complex | |
| * data of this object, it should first get a StateTracker | |
| * object from this method so that it can check if such | |
| * information is current upon future uses. | |
| * Note that a valid StateTracker will always be returned | |
| * regardless of the return value of getState(), but in some | |
| * cases the StateTracker may be a trivial implementation | |
| * which always returns the same value from its | |
| * {@link StateTracker#isCurrent isCurrent} method. | |
| * <ul> | |
| * <li>If the current state is {@link State#IMMUTABLE IMMUTABLE}, | |
| * this StateTracker and any future StateTracker objects | |
| * returned from this method will always indicate that | |
| * the state has not changed.</li> | |
| * <li>If the current state is {@link State#UNTRACKABLE UNTRACKABLE}, | |
| * this StateTracker and any future StateTracker objects | |
| * returned from this method will always indicate that | |
| * the state has changed.</li> | |
| * <li>If the current state is {@link State#DYNAMIC DYNAMIC}, | |
| * this StateTracker may always indicate that the current | |
| * state has changed, but another StateTracker returned | |
| * from this method in the future when the state has changed | |
| * to {@link State#STABLE STABLE} will correctly track changes.</li> | |
| * <li>Otherwise the current state is {@link State#STABLE STABLE} | |
| * and this StateTracker will indicate whether or not the | |
| * data has changed since the time at which it was fetched | |
| * from the object.</li> | |
| * </ul> | |
| * @return an object implementing the StateTracker interface | |
| * that tracks whether changes have been made to the complex | |
| * contents of this object since it was returned. | |
| * @see State | |
| * @see #getState | |
| * @since 1.7 | |
| */ | |
| public StateTracker getStateTracker(); | |
| } |