/* * 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</code> * reference to null in the usage pattern above effectively invalidates * all outstanding <code>Tracker</code> 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();}
/*
* 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</code>
* reference to null in the usage pattern above effectively invalidates
* all outstanding <code>Tracker</code> 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();
}