2
|
1 |
/*
|
5506
|
2 |
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
2
|
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
|
5506
|
7 |
* published by the Free Software Foundation. Oracle designates this
|
2
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
5506
|
9 |
* by Oracle in the LICENSE file that accompanied this code.
|
2
|
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 |
*
|
5506
|
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.
|
2
|
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 |
}
|