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 }