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