Path: blob/master/src/java.desktop/share/classes/sun/java2d/StateTrackable.java
41152 views
/*1* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d;2627/**28* This interface is implemented by classes which contain complex state29* so that other objects can track whether or not their state has changed30* since earlier interactions with the object.31* <p>32* The suggested usage pattern for code that manages some trackable data33* is as follows:34* <pre>35* class Trackable implements StateTrackable {36* TrackedInfo data;37* State curState = STABLE;38* StateTracker curTracker = null;39* // Hypothetical method to return a static piece of our tracked data.40* // Assume that Datum is either a copy of some piece of the tracked41* // data or that it is itself immutable.42* public Datum getSomeDatum(int key) {43* // No need to modify the state for this type of "get" call.44* return data.getDatum(key);45* }46* // Hypothetical method to return a raw reference to our tracked data.47* public TrackedInfo getRawHandleToInfo() {48* // Since we are returning a raw reference to our tracked49* // data and since we can not track what the caller will50* // do with that reference, we can no longer track the51* // state of this data.52* synchronized (this) {53* // Note: modifying both curState and curTracker requires54* // synchronization against the getStateTracker method.55* curState = UNTRACKABLE;56* curTracker = null;57* }58* return data;59* }60* // Hypothetical method to set a single piece of data to some61* // new static value.62* public void setSomeDatum(int key, Datum datum) {63* data.setDatum(key, datum);64* // We do not need to change state for this, we simply65* // invalidate the outstanding StateTracker objects.66* // Note: setting curTracker to null requires no synchronization.67* curTracker = null;68* }69* // getStateTracker must be synchronized against any code that70* // changes the State.71* public synchronized StateTracker getStateTracker() {72* StateTracker st = curTracker;73* if (st == null) {74* switch (curState) {75* case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break;76* case STABLE: st = new Tracker(this); break;77* case DYNAMIC: st = StateTracker.NEVER_CURRENT; break;78* case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break;79* }80* curTracker = st;81* }82* return st;83* }84*85* static class Tracker implements StateTracker {86* Trackable theTrackable;87* public Tracker(Trackable t) {88* theTrackable = t;89* }90* public boolean isCurrent() {91* return (theTrackable.curTracker == this);92* }93* }94* }95* </pre>96* Note that the mechanism shown above for invalidating outstanding97* StateTracker objects is not the most theoretically conservative98* way to implement state tracking in a "set" method.99* There is a small window of opportunity after the data has changed100* before the outstanding StateTracker objects are invalidated and101* where they will indicate that the data is still the same as when102* they were instantiated.103* While this is technically inaccurate, it is acceptable since the more104* conservative approaches to state management are much more complex and105* cost much more in terms of performance for a very small gain in106* correctness.107* For example:108* <p>109* The most conservative approach would be to synchronize all accesses110* and all modifications to the data, including its State.111* This would require synchronized blocks around some potentially large112* bodies of code which would impact the multi-threaded scalability of113* the implementation.114* Further, if data is to be coordinated or transferred between two115* trackable objects then both would need to be synchronized raising116* the possibility of deadlock unless some strict rules of priority117* for the locking of the objects were established and followed118* religiously.119* Either or both of these drawbacks makes such an implementation120* infeasible.121* <p>122* A less conservative approach would be to change the state of the123* trackable object to DYNAMIC during all modifications of the data124* and then to change it back to STABLE after those modifications125* are complete.126* While this state transition more accurately reflects the temporary127* loss of tracking during the modification phase, in reality the128* time period of the modifications would be small in most cases129* and the 2 changes of state would each require synchronization.130* <p>131* In comparison the act of setting the {@code curTracker}132* reference to null in the usage pattern above effectively invalidates133* all outstanding {@code Tracker} objects as soon as possible134* after the change to the data and requires very little code and no135* synchronization to implement.136* <p>137* In the end it is up to the implementor of a StateTrackable object138* how fine the granularity of State updates should be managed based139* on the frequency and atomicity of the modifications and the140* consequences of returning an inaccurate State for a particularly141* small window of opportunity.142* Most implementations are likely to follow the liberal, but efficient143* guidelines found in the usage pattern proposed above.144*145* @since 1.7146*/147public interface StateTrackable {148/**149* An enumeration describing the current state of a trackable150* object.151* These values describe how often the complex data contained152* in a trackable object can be changed and whether or not it153* makes sense to try to track the data in its current state.154* @see StateTrackable#getState155* @since 1.7156*/157public enum State {158/**159* The complex data will never change again.160* Information related to the current contents of the complex161* data can be calculated and cached indefinitely with no162* further checks to see if the information is stale.163*/164IMMUTABLE,165166/**167* The complex data is currently stable, but could change at168* some point in the future.169* Information related to the current contents of the complex170* data can be calculated and cached, but a StateTracker should171* be used to verify the freshness of such precalculated data172* before each future use.173*/174STABLE,175176/**177* The complex data is currently in flux and is frequently178* changing.179* While information related to the current contents of the180* complex data could be calculated and cached, there is a181* reasonably high probability that the cached information182* would be found to be out of date by the next time it is183* used.184* It may also be the case that the current contents are185* temporarily untrackable, but that they may become trackable186* again in the future.187*/188DYNAMIC,189190/**191* The complex data can currently be changed by external192* references and agents in a way that cannot be tracked.193* If any information about the current contents of the complex194* data were to be cached, there would be no way to determine195* whether or not that cached information was out of date.196*/197UNTRACKABLE,198};199200/**201* Returns the general state of the complex data held by this202* object.203* This return value can be used to determine if it makes204* strategic sense to try and cache information about the current205* contents of this object.206* The StateTracker returned from the getStateTracker() method207* will further aid in determining when the data has been208* changed so that the caches can be verified upon future uses.209* @return the current state of trackability of the complex210* data stored in this object.211* @see #getStateTracker212* @since 1.7213*/214public State getState();215216/**217* Returns an object which can track future changes to the218* complex data stored in this object.219* If an external agent caches information about the complex220* data of this object, it should first get a StateTracker221* object from this method so that it can check if such222* information is current upon future uses.223* Note that a valid StateTracker will always be returned224* regardless of the return value of getState(), but in some225* cases the StateTracker may be a trivial implementation226* which always returns the same value from its227* {@link StateTracker#isCurrent isCurrent} method.228* <ul>229* <li>If the current state is {@link State#IMMUTABLE IMMUTABLE},230* this StateTracker and any future StateTracker objects231* returned from this method will always indicate that232* the state has not changed.</li>233* <li>If the current state is {@link State#UNTRACKABLE UNTRACKABLE},234* this StateTracker and any future StateTracker objects235* returned from this method will always indicate that236* the state has changed.</li>237* <li>If the current state is {@link State#DYNAMIC DYNAMIC},238* this StateTracker may always indicate that the current239* state has changed, but another StateTracker returned240* from this method in the future when the state has changed241* to {@link State#STABLE STABLE} will correctly track changes.</li>242* <li>Otherwise the current state is {@link State#STABLE STABLE}243* and this StateTracker will indicate whether or not the244* data has changed since the time at which it was fetched245* from the object.</li>246* </ul>247* @return an object implementing the StateTracker interface248* that tracks whether changes have been made to the complex249* contents of this object since it was returned.250* @see State251* @see #getState252* @since 1.7253*/254public StateTracker getStateTracker();255}256257258