Showing the changes to java/pkg/sun/java2d/StateTrackable.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,256 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. | |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 4 | + * | |
| 5 | + * This code is free software; you can redistribute it and/or modify it | |
| 6 | + * under the terms of the GNU General Public License version 2 only, as | |
| 7 | + * published by the Free Software Foundation. Oracle designates this | |
| 8 | + * particular file as subject to the "Classpath" exception as provided | |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 10 | + * | |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 15 | + * accompanied this code). | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License version | |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 20 | + * | |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 22 | + * or visit www.oracle.com if you need additional information or have any | |
| 23 | + * questions. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +package sun.java2d; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * This interface is implemented by classes which contain complex state | |
| 30 | + * so that other objects can track whether or not their state has changed | |
| 31 | + * since earlier interactions with the object. | |
| 32 | + * <p> | |
| 33 | + * The suggested usage pattern for code that manages some trackable data | |
| 34 | + * is as follows: | |
| 35 | + * <pre> | |
| 36 | + * class Trackable implements StateTrackable { | |
| 37 | + * TrackedInfo data; | |
| 38 | + * State curState = STABLE; | |
| 39 | + * StateTracker curTracker = null; | |
| 40 | + * // Hypothetical method to return a static piece of our tracked data. | |
| 41 | + * // Assume that Datum is either a copy of some piece of the tracked | |
| 42 | + * // data or that it is itself immutable. | |
| 43 | + * public Datum getSomeDatum(int key) { | |
| 44 | + * // No need to modify the state for this type of "get" call. | |
| 45 | + * return data.getDatum(key); | |
| 46 | + * } | |
| 47 | + * // Hypothetical method to return a raw reference to our tracked data. | |
| 48 | + * public TrackedInfo getRawHandleToInfo() { | |
| 49 | + * // Since we are returning a raw reference to our tracked | |
| 50 | + * // data and since we can not track what the caller will | |
| 51 | + * // do with that reference, we can no longer track the | |
| 52 | + * // state of this data. | |
| 53 | + * synchronized (this) { | |
| 54 | + * // Note: modifying both curState and curTracker requires | |
| 55 | + * // synchronization against the getStateTracker method. | |
| 56 | + * curState = UNTRACKABLE; | |
| 57 | + * curTracker = null; | |
| 58 | + * } | |
| 59 | + * return data; | |
| 60 | + * } | |
| 61 | + * // Hypothetical method to set a single piece of data to some | |
| 62 | + * // new static value. | |
| 63 | + * public void setSomeDatum(int key, Datum datum) { | |
| 64 | + * data.setDatum(key, datum); | |
| 65 | + * // We do not need to change state for this, we simply | |
| 66 | + * // invalidate the outstanding StateTracker objects. | |
| 67 | + * // Note: setting curTracker to null requires no synchronization. | |
| 68 | + * curTracker = null; | |
| 69 | + * } | |
| 70 | + * // getStateTracker must be synchronized against any code that | |
| 71 | + * // changes the State. | |
| 72 | + * public synchronized StateTracker getStateTracker() { | |
| 73 | + * StateTracker st = curTracker; | |
| 74 | + * if (st == null) { | |
| 75 | + * switch (curState) { | |
| 76 | + * case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break; | |
| 77 | + * case STABLE: st = new Tracker(this); break; | |
| 78 | + * case DYNAMIC: st = StateTracker.NEVER_CURRENT; break; | |
| 79 | + * case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break; | |
| 80 | + * } | |
| 81 | + * curTracker = st; | |
| 82 | + * } | |
| 83 | + * return st; | |
| 84 | + * } | |
| 85 | + * | |
| 86 | + * static class Tracker implements StateTracker { | |
| 87 | + * Trackable theTrackable; | |
| 88 | + * public Tracker(Trackable t) { | |
| 89 | + * theTrackable = t; | |
| 90 | + * } | |
| 91 | + * public boolean isCurrent() { | |
| 92 | + * return (theTrackable.curTracker == this); | |
| 93 | + * } | |
| 94 | + * } | |
| 95 | + * } | |
| 96 | + * </pre> | |
| 97 | + * Note that the mechanism shown above for invalidating outstanding | |
| 98 | + * StateTracker objects is not the most theoretically conservative | |
| 99 | + * 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 | +} | |