0N/A/*
2362N/A * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.java2d;
0N/A
0N/A/**
0N/A * This interface is implemented by classes which contain complex state
0N/A * so that other objects can track whether or not their state has changed
0N/A * since earlier interactions with the object.
0N/A * <p>
0N/A * The suggested usage pattern for code that manages some trackable data
0N/A * is as follows:
0N/A * <pre>
0N/A * class Trackable implements StateTrackable {
0N/A * TrackedInfo data;
0N/A * State curState = STABLE;
0N/A * StateTracker curTracker = null;
0N/A * // Hypothetical method to return a static piece of our tracked data.
0N/A * // Assume that Datum is either a copy of some piece of the tracked
0N/A * // data or that it is itself immutable.
0N/A * public Datum getSomeDatum(int key) {
0N/A * // No need to modify the state for this type of "get" call.
0N/A * return data.getDatum(key);
0N/A * }
0N/A * // Hypothetical method to return a raw reference to our tracked data.
0N/A * public TrackedInfo getRawHandleToInfo() {
0N/A * // Since we are returning a raw reference to our tracked
0N/A * // data and since we can not track what the caller will
0N/A * // do with that reference, we can no longer track the
0N/A * // state of this data.
0N/A * synchronized (this) {
0N/A * // Note: modifying both curState and curTracker requires
0N/A * // synchronization against the getStateTracker method.
0N/A * curState = UNTRACKABLE;
0N/A * curTracker = null;
0N/A * }
0N/A * return data;
0N/A * }
0N/A * // Hypothetical method to set a single piece of data to some
0N/A * // new static value.
0N/A * public void setSomeDatum(int key, Datum datum) {
0N/A * data.setDatum(key, datum);
0N/A * // We do not need to change state for this, we simply
0N/A * // invalidate the outstanding StateTracker objects.
0N/A * // Note: setting curTracker to null requires no synchronization.
0N/A * curTracker = null;
0N/A * }
0N/A * // getStateTracker must be synchronized against any code that
0N/A * // changes the State.
0N/A * public synchronized StateTracker getStateTracker() {
0N/A * StateTracker st = curTracker;
0N/A * if (st == null) {
0N/A * switch (curState) {
0N/A * case IMMUTABLE: st = StateTracker.ALWAYS_CURRENT; break;
0N/A * case STABLE: st = new Tracker(this); break;
0N/A * case DYNAMIC: st = StateTracker.NEVER_CURRENT; break;
0N/A * case UNTRACKABLE: st = StateTracker.NEVER_CURRENT; break;
0N/A * }
0N/A * curTracker = st;
0N/A * }
0N/A * return st;
0N/A * }
0N/A *
0N/A * static class Tracker implements StateTracker {
0N/A * Trackable theTrackable;
0N/A * public Tracker(Trackable t) {
0N/A * theTrackable = t;
0N/A * }
0N/A * public boolean isCurrent() {
0N/A * return (theTrackable.curTracker == this);
0N/A * }
0N/A * }
0N/A * }
0N/A * </pre>
0N/A * Note that the mechanism shown above for invalidating outstanding
0N/A * StateTracker objects is not the most theoretically conservative
0N/A * way to implement state tracking in a "set" method.
0N/A * There is a small window of opportunity after the data has changed
0N/A * before the outstanding StateTracker objects are invalidated and
0N/A * where they will indicate that the data is still the same as when
0N/A * they were instantiated.
0N/A * While this is technically inaccurate, it is acceptable since the more
0N/A * conservative approaches to state management are much more complex and
0N/A * cost much more in terms of performance for a very small gain in
0N/A * correctness.
0N/A * For example:
0N/A * <p>
0N/A * The most conservative approach would be to synchronize all accesses
0N/A * and all modifications to the data, including its State.
0N/A * This would require synchronized blocks around some potentially large
0N/A * bodies of code which would impact the multi-threaded scalability of
0N/A * the implementation.
0N/A * Further, if data is to be coordinated or transferred between two
0N/A * trackable objects then both would need to be synchronized raising
0N/A * the possibility of deadlock unless some strict rules of priority
0N/A * for the locking of the objects were established and followed
0N/A * religiously.
0N/A * Either or both of these drawbacks makes such an implementation
0N/A * infeasible.
0N/A * <p>
0N/A * A less conservative approach would be to change the state of the
0N/A * trackable object to DYNAMIC during all modifications of the data
0N/A * and then to change it back to STABLE after those modifications
0N/A * are complete.
0N/A * While this state transition more accurately reflects the temporary
0N/A * loss of tracking during the modification phase, in reality the
0N/A * time period of the modifications would be small in most cases
0N/A * and the 2 changes of state would each require synchronization.
0N/A * <p>
0N/A * In comparison the act of setting the <code>curTracker</code>
0N/A * reference to null in the usage pattern above effectively invalidates
0N/A * all outstanding <code>Tracker</code> objects as soon as possible
0N/A * after the change to the data and requires very little code and no
0N/A * synchronization to implement.
0N/A * <p>
0N/A * In the end it is up to the implementor of a StateTrackable object
0N/A * how fine the granularity of State updates should be managed based
0N/A * on the frequency and atomicity of the modifications and the
0N/A * consequences of returning an inaccurate State for a particularly
0N/A * small window of opportunity.
0N/A * Most implementations are likely to follow the liberal, but efficient
0N/A * guidelines found in the usage pattern proposed above.
0N/A *
0N/A * @since 1.7
0N/A */
0N/Apublic interface StateTrackable {
0N/A /**
0N/A * An enumeration describing the current state of a trackable
0N/A * object.
0N/A * These values describe how often the complex data contained
0N/A * in a trackable object can be changed and whether or not it
0N/A * makes sense to try to track the data in its current state.
0N/A * @see StateTrackable#getState
0N/A * @since 1.7
0N/A */
0N/A public enum State {
0N/A /**
0N/A * The complex data will never change again.
0N/A * Information related to the current contents of the complex
0N/A * data can be calculated and cached indefinitely with no
0N/A * further checks to see if the information is stale.
0N/A */
0N/A IMMUTABLE,
0N/A
0N/A /**
0N/A * The complex data is currently stable, but could change at
0N/A * some point in the future.
0N/A * Information related to the current contents of the complex
0N/A * data can be calculated and cached, but a StateTracker should
0N/A * be used to verify the freshness of such precalculated data
0N/A * before each future use.
0N/A */
0N/A STABLE,
0N/A
0N/A /**
0N/A * The complex data is currently in flux and is frequently
0N/A * changing.
0N/A * While information related to the current contents of the
0N/A * complex data could be calculated and cached, there is a
0N/A * reasonably high probability that the cached information
0N/A * would be found to be out of date by the next time it is
0N/A * used.
0N/A * It may also be the case that the current contents are
0N/A * temporarily untrackable, but that they may become trackable
0N/A * again in the future.
0N/A */
0N/A DYNAMIC,
0N/A
0N/A /**
0N/A * The complex data can currently be changed by external
0N/A * references and agents in a way that cannot be tracked.
0N/A * If any information about the current contents of the complex
0N/A * data were to be cached, there would be no way to determine
0N/A * whether or not that cached information was out of date.
0N/A */
0N/A UNTRACKABLE,
0N/A };
0N/A
0N/A /**
0N/A * Returns the general state of the complex data held by this
0N/A * object.
0N/A * This return value can be used to determine if it makes
0N/A * strategic sense to try and cache information about the current
0N/A * contents of this object.
0N/A * The StateTracker returned from the getStateTracker() method
0N/A * will further aid in determining when the data has been
0N/A * changed so that the caches can be verified upon future uses.
0N/A * @return the current state of trackability of the complex
0N/A * data stored in this object.
0N/A * @see #getStateTracker
0N/A * @since 1.7
0N/A */
0N/A public State getState();
0N/A
0N/A /**
0N/A * Returns an object which can track future changes to the
0N/A * complex data stored in this object.
0N/A * If an external agent caches information about the complex
0N/A * data of this object, it should first get a StateTracker
0N/A * object from this method so that it can check if such
0N/A * information is current upon future uses.
0N/A * Note that a valid StateTracker will always be returned
0N/A * regardless of the return value of getState(), but in some
0N/A * cases the StateTracker may be a trivial implementation
0N/A * which always returns the same value from its
0N/A * {@link StateTracker#isCurrent isCurrent} method.
0N/A * <ul>
0N/A * <li>If the current state is {@link State#IMMUTABLE IMMUTABLE},
0N/A * this StateTracker and any future StateTracker objects
0N/A * returned from this method will always indicate that
0N/A * the state has not changed.</li>
0N/A * <li>If the current state is {@link State#UNTRACKABLE UNTRACKABLE},
0N/A * this StateTracker and any future StateTracker objects
0N/A * returned from this method will always indicate that
0N/A * the state has changed.</li>
0N/A * <li>If the current state is {@link State#DYNAMIC DYNAMIC},
0N/A * this StateTracker may always indicate that the current
0N/A * state has changed, but another StateTracker returned
0N/A * from this method in the future when the state has changed
0N/A * to {@link State#STABLE STABLE} will correctly track changes.</li>
0N/A * <li>Otherwise the current state is {@link State#STABLE STABLE}
0N/A * and this StateTracker will indicate whether or not the
0N/A * data has changed since the time at which it was fetched
0N/A * from the object.</li>
0N/A * </ul>
0N/A * @return an object implementing the StateTracker interface
0N/A * that tracks whether changes have been made to the complex
0N/A * contents of this object since it was returned.
0N/A * @see State
0N/A * @see #getState
0N/A * @since 1.7
0N/A */
0N/A public StateTracker getStateTracker();
0N/A}