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 26package 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} 133 * reference to null in the usage pattern above effectively invalidates 134 * all outstanding {@code Tracker} 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 */ 148public 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} 257