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 | } | ||