2 ******************************************************************************
\r
3 * Copyright (C) 200-2009, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 ******************************************************************************
\r
7 package com.ibm.icu.util;
\r
10 * Provides a flexible mechanism for controlling access, without requiring that
\r
11 * a class be immutable. Once locked, an object can never be unlocked, so it is
\r
12 * thread-safe from that point onward. The implementation of both methods must
\r
13 * be synchronized. Once the object has been locked, it must guarantee that no
\r
14 * changes can be made to it. Any attempt to alter it must raise an
\r
15 * UnsupportedOperationException exception. This means that when the object
\r
16 * returns internal objects, or if anyone has references to those internal
\r
17 * objects, that those internal objects must either be immutable, or must also
\r
18 * raise exceptions if any attempt to modify them is made. Of course, the object
\r
19 * can return clones of internal objects, since those are safe.
\r
20 * <h2>Background</h2>
\r
22 * There are often times when you need objects to be objects 'safe', so that
\r
23 * they can't be modified. Examples are when objects need to be thread-safe, or
\r
24 * in writing robust code, or in caches. If you are only creating your own
\r
25 * objects, you can guarantee this, of course -- but only if you don't make a
\r
26 * mistake. If you have objects handed into you, or are creating objects using
\r
27 * others handed into you, it is a different story. It all comes down to whether
\r
28 * you want to take the Blanche Dubois approach ("depend on the kindness of
\r
29 * strangers") or the Andy Grove approach ("Only the Paranoid
\r
33 * For example, suppose we have a simple class:
\r
38 * protected Collection b;
\r
40 * protected Collection c;
\r
42 * public Collection get_b() {
\r
46 * public Collection get_c() {
\r
50 * public A(Collection new_b, Collection new_c) {
\r
58 * Since the class doesn't have any setters, someone might think that it is
\r
59 * immutable. You know where this is leading, of course; this class is unsafe in
\r
60 * a number of ways. The following illustrates that.
\r
64 * public test1(SupposedlyImmutableClass x, SafeStorage y) {
\r
67 * Collection col = a.get_b();
\r
68 * col.add(something); // a has now been changed, and x too
\r
70 * // unsafe constructor
\r
71 * a = new A(col, col);
\r
73 * col.add(something); // a has now been changed, and y too
\r
78 * There are a few different techniques for having safe classes.
\r
81 * <li>Const objects. In C++, you can declare parameters const.</li>
\r
82 * <li>Immutable wrappers. For example, you can put a collection in an
\r
83 * immutable wrapper.</li>
\r
84 * <li>Always-Immutable objects. Java uses this approach, with a few
\r
85 * variations. Examples:
\r
87 * <li>Simple. Once a Color is created (eg from R, G, and B integers) it is
\r
89 * <li>Builder Class. There is a separate 'builder' class. For example,
\r
90 * modifiable Strings are created using StringBuffer (which doesn't have the
\r
91 * full String API available). Once you want an immutable form, you create one
\r
92 * with toString().</li>
\r
93 * <li>Primitives. These are always safe, since they are copied on input/output
\r
94 * from methods.</li>
\r
97 * <li>Cloning. Where you need an object to be safe, you clone it.</li>
\r
100 * There are advantages and disadvantages of each of these.
\r
103 * <li>Const provides a certain level of protection, but since const can be and
\r
104 * is often cast away, it only protects against most inadvertent mistakes. It
\r
105 * also offers no threading protection, since anyone who has a pointer to the
\r
106 * (unconst) object in another thread can mess you up.</li>
\r
107 * <li>Immutable wrappers are safer than const in that the constness can't be
\r
108 * cast away. But other than that they have all the same problems: not safe if
\r
109 * someone else keeps hold of the original object, or if any of the objects
\r
110 * returned by the class are mutable.</li>
\r
111 * <li>Always-Immutable Objects are safe, but usage can require excessive
\r
112 * object creation.</li>
\r
113 * <li>Cloning is only safe if the object truly has a 'safe' clone; defined as
\r
114 * one that <i>ensures that no change to the clone affects the original</i>.
\r
115 * Unfortunately, many objects don't have a 'safe' clone, and always cloning can
\r
116 * require excessive object creation.</li>
\r
118 * <h2>Freezable Model</h2>
\r
120 * The <code>Freezable</code> model supplements these choices by giving you
\r
121 * the ability to build up an object by calling various methods, then when it is
\r
122 * in a final state, you can <i>make</i> it immutable. Once immutable, an
\r
123 * object cannot <i>ever </i>be modified, and is completely thread-safe: that
\r
124 * is, multiple threads can have references to it without any synchronization.
\r
125 * If someone needs a mutable version of an object, they can use
\r
126 * <code>cloneAsThawed()</code>, and modify the copy. This provides a simple,
\r
127 * effective mechanism for safe classes in circumstances where the alternatives
\r
128 * are insufficient or clumsy. (If an object is shared before it is immutable,
\r
129 * then it is the responsibility of each thread to mutex its usage (as with
\r
133 * Here is what needs to be done to implement this interface, depending on the
\r
134 * type of the object.
\r
136 * <h3><b>Immutable Objects</b></h3>
\r
138 * These are the easiest. You just use the interface to reflect that, by adding
\r
143 * public class A implements Freezable<A> {
\r
145 * public final boolean isFrozen() {return true;}
\r
146 * public final A freeze() {return this;}
\r
147 * public final A cloneAsThawed() { return this; }
\r
152 * These can be final methods because subclasses of immutable objects must
\r
153 * themselves be immutable. (Note: <code>freeze</code> is returning
\r
154 * <code>this</code> for chaining.)
\r
156 * <h3><b>Mutable Objects</b></h3>
\r
158 * Add a protected 'flagging' field:
\r
162 * protected boolean immutable;
\r
166 * Add the following methods:
\r
170 * public final boolean isFrozen() {
\r
174 * public A freeze() {
\r
181 * Add a <code>cloneAsThawed()</code> method following the normal pattern for
\r
182 * <code>clone()</code>, except that <code>frozen=false</code> in the new
\r
186 * Then take the setters (that is, any method that can change the internal state
\r
187 * of the object), and add the following as the first statement:
\r
191 * if (isFrozen()) {
\r
192 * throw new UnsupportedOperationException("Attempt to modify frozen object");
\r
196 * <h4><b>Subclassing</b></h4>
\r
198 * Any subclass of a <code>Freezable</code> will just use its superclass's
\r
199 * flagging field. It must override <code>freeze()</code> and
\r
200 * <code>cloneAsThawed()</code> to call the superclass, but normally does not
\r
201 * override <code>isFrozen()</code>. It must then just pay attention to its
\r
202 * own getters, setters and fields.
\r
204 * <h4><b>Internal Caches</b></h4>
\r
206 * Internal caches are cases where the object is logically unmodified, but
\r
207 * internal state of the object changes. For example, there are const C++
\r
208 * functions that cast away the const on the "this" pointer in order
\r
209 * to modify an object cache. These cases are handled by mutexing the internal
\r
210 * cache to ensure thread-safety. For example, suppose that UnicodeSet had an
\r
211 * internal marker to the last code point accessed. In this case, the field is
\r
212 * not externally visible, so the only thing you need to do is to synchronize
\r
213 * the field for thread safety.
\r
215 * <h4>Unsafe Internal Access</h4>
\r
217 * Internal fields are called <i>safe</i> if they are either
\r
218 * <code>frozen</code> or immutable (such as String or primitives). If you've
\r
219 * never allowed internal access to these, then you are all done. For example,
\r
220 * converting UnicodeSet to be <code>Freezable</code> is just accomplished
\r
221 * with the above steps. But remember that you <i><b>have</b></i> allowed
\r
222 * access to unsafe internals if you have any code like the following, in a
\r
223 * getter, setter, or constructor:
\r
227 * Collection getStuff() {
\r
229 * } // caller could keep reference & modify
\r
231 * void setStuff(Collection x) {
\r
233 * } // caller could keep reference & modify
\r
235 * MyClass(Collection x) {
\r
237 * } // caller could keep reference & modify
\r
241 * These also illustrated in the code sample in <b>Background</b> above.
\r
244 * To deal with unsafe internals, the simplest course of action is to do the
\r
245 * work in the <code>freeze()</code> function. Just make all of your internal
\r
246 * fields frozen, and set the frozen flag. Any subsequent getter/setter will
\r
247 * work properly. Here is an example:
\r
251 * public A freeze() {
\r
261 * If the field is a <code>Collection</code> or <code>Map</code>, then to
\r
262 * make it frozen you have two choices. If you have never allowed access to the
\r
263 * collection from outside your object, then just wrap it to prevent future
\r
268 * zone_to_country = Collections.unmodifiableMap(zone_to_country);
\r
272 * If you have <i>ever</i> allowed access, then do a <code>clone()</code>
\r
273 * before wrapping it.
\r
277 * zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());
\r
281 * If a collection <i>(or any other container of objects)</i> itself can
\r
282 * contain mutable objects, then for a safe clone you need to recurse through it
\r
283 * to make the entire collection immutable. The recursing code should pick the
\r
284 * most specific collection available, to avoid the necessity of later
\r
289 * <b>Note: </b>An annoying flaw in Java is that the generic collections, like
\r
290 * <code>Map</code> or <code>Set</code>, don't have a <code>clone()</code>
\r
291 * operation. When you don't know the type of the collection, the simplest
\r
292 * course is to just create a new collection:
\r
296 * zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));
\r
302 public interface Freezable<T> extends Cloneable {
\r
304 * Determines whether the object has been locked or not.
\r
307 public boolean isFrozen();
\r
310 * Locks the object.
\r
311 * @return the object itself.
\r
317 * Provides for the clone operation. Any clone is initially unlocked.
\r
320 public T cloneAsThawed();
\r