KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > concurrent > atomic > AtomicReferenceFieldUpdater


1 /*
2  * @(#)AtomicReferenceFieldUpdater.java 1.9 05/08/09
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.concurrent.atomic;
9 import sun.misc.Unsafe;
10 import java.lang.reflect.*;
11
12 /**
13  * A reflection-based utility that enables atomic updates to
14  * designated <tt>volatile</tt> reference fields of designated
15  * classes. This class is designed for use in atomic data structures
16  * in which several reference fields of the same node are
17  * independently subject to atomic updates. For example, a tree node
18  * might be declared as
19  *
20  * <pre>
21  * class Node {
22  * private volatile Node left, right;
23  *
24  * private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
25  * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
26  * private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
27  * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
28  *
29  * Node getLeft() { return left; }
30  * boolean compareAndSetLeft(Node expect, Node update) {
31  * return leftUpdater.compareAndSet(this, expect, update);
32  * }
33  * // ... and so on
34  * }
35  * </pre>
36  *
37  * <p> Note that the guarantees of the <tt>compareAndSet</tt>
38  * method in this class are weaker than in other atomic classes. Because this
39  * class cannot ensure that all uses of the field are appropriate for
40  * purposes of atomic access, it can guarantee atomicity and volatile
41  * semantics only with respect to other invocations of
42  * <tt>compareAndSet</tt> and <tt>set</tt>.
43  * @since 1.5
44  * @author Doug Lea
45  * @param <T> The type of the object holding the updatable field
46  * @param <V> The type of the field
47  */

48 public abstract class AtomicReferenceFieldUpdater<T, V> {
49
50     /**
51      * Creates an updater for objects with the given field. The Class
52      * arguments are needed to check that reflective types and generic
53      * types match.
54      * @param tclass the class of the objects holding the field.
55      * @param vclass the class of the field
56      * @param fieldName the name of the field to be updated.
57      * @return the updater
58      * @throws IllegalArgumentException if the field is not a volatile reference type.
59      * @throws RuntimeException with a nested reflection-based
60      * exception if the class does not hold field or is the wrong type.
61      */

62     public static <U, W> AtomicReferenceFieldUpdater JavaDoc<U,W> newUpdater(Class JavaDoc<U> tclass, Class JavaDoc<W> vclass, String JavaDoc fieldName) {
63         // Currently rely on standard intrinsics implementation
64
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
65                                                         vclass,
66                                                         fieldName);
67     }
68
69     /**
70      * Protected do-nothing constructor for use by subclasses.
71      */

72     protected AtomicReferenceFieldUpdater() {
73     }
74
75     /**
76      * Atomically set the value of the field of the given object managed
77      * by this Updater to the given updated value if the current value
78      * <tt>==</tt> the expected value. This method is guaranteed to be
79      * atomic with respect to other calls to <tt>compareAndSet</tt> and
80      * <tt>set</tt>, but not necessarily with respect to other
81      * changes in the field.
82      * @param obj An object whose field to conditionally set
83      * @param expect the expected value
84      * @param update the new value
85      * @return true if successful.
86      */

87
88     public abstract boolean compareAndSet(T obj, V expect, V update);
89
90     /**
91      * Atomically set the value of the field of the given object managed
92      * by this Updater to the given updated value if the current value
93      * <tt>==</tt> the expected value. This method is guaranteed to be
94      * atomic with respect to other calls to <tt>compareAndSet</tt> and
95      * <tt>set</tt>, but not necessarily with respect to other
96      * changes in the field, and may fail spuriously.
97      * @param obj An object whose field to conditionally set
98      * @param expect the expected value
99      * @param update the new value
100      * @return true if successful.
101      */

102     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
103
104     /**
105      * Set the field of the given object managed by this updater. This
106      * operation is guaranteed to act as a volatile store with respect
107      * to subsequent invocations of <tt>compareAndSet</tt>.
108      * @param obj An object whose field to set
109      * @param newValue the new value
110      */

111     public abstract void set(T obj, V newValue);
112
113     /**
114      * Get the current value held in the field by the given object.
115      * @param obj An object whose field to get
116      * @return the current value
117      */

118     public abstract V get(T obj);
119
120     /**
121      * Set to the given value and return the old value.
122      *
123      * @param obj An object whose field to get and set
124      * @param newValue the new value
125      * @return the previous value
126      */

127     public V getAndSet(T obj, V newValue) {
128         for (;;) {
129             V current = get(obj);
130             if (compareAndSet(obj, current, newValue))
131                 return current;
132         }
133     }
134
135     /**
136      * Standard hotspot implementation using intrinsics
137      */

138     private static class AtomicReferenceFieldUpdaterImpl<T,V> extends AtomicReferenceFieldUpdater JavaDoc<T,V> {
139         private static final Unsafe unsafe = Unsafe.getUnsafe();
140         private final long offset;
141         private final Class JavaDoc<T> tclass;
142         private final Class JavaDoc<V> vclass;
143         private final Class JavaDoc cclass;
144
145         AtomicReferenceFieldUpdaterImpl(Class JavaDoc<T> tclass, Class JavaDoc<V> vclass, String JavaDoc fieldName) {
146             Field field = null;
147             Class JavaDoc fieldClass = null;
148         Class JavaDoc caller = null;
149         int modifiers = 0;
150             try {
151                 field = tclass.getDeclaredField(fieldName);
152         caller = sun.reflect.Reflection.getCallerClass(3);
153         modifiers = field.getModifiers();
154                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
155                     caller, tclass, null, modifiers);
156         sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
157                 fieldClass = field.getType();
158             } catch(Exception JavaDoc ex) {
159                 throw new RuntimeException JavaDoc(ex);
160             }
161             
162             if (vclass != fieldClass)
163                 throw new ClassCastException JavaDoc();
164             
165             if (!Modifier.isVolatile(modifiers))
166                 throw new IllegalArgumentException JavaDoc("Must be volatile type");
167
168         this.cclass = (Modifier.isProtected(modifiers) &&
169                caller != tclass) ? caller : null;
170             this.tclass = tclass;
171             this.vclass = vclass;
172             offset = unsafe.objectFieldOffset(field);
173         }
174         
175
176         public boolean compareAndSet(T obj, V expect, V update) {
177             if (!tclass.isInstance(obj) ||
178                 (update != null && !vclass.isInstance(update)))
179                 throw new ClassCastException JavaDoc();
180         if (cclass != null)
181             ensureProtectedAccess(obj);
182             return unsafe.compareAndSwapObject(obj, offset, expect, update);
183         }
184
185         public boolean weakCompareAndSet(T obj, V expect, V update) {
186             // same implementation as strong form for now
187
if (!tclass.isInstance(obj) ||
188                 (update != null && !vclass.isInstance(update)))
189                 throw new ClassCastException JavaDoc();
190         if (cclass != null)
191             ensureProtectedAccess(obj);
192             return unsafe.compareAndSwapObject(obj, offset, expect, update);
193         }
194
195
196         public void set(T obj, V newValue) {
197             if (!tclass.isInstance(obj) ||
198                 (newValue != null && !vclass.isInstance(newValue)))
199                 throw new ClassCastException JavaDoc();
200         if (cclass != null)
201             ensureProtectedAccess(obj);
202             unsafe.putObjectVolatile(obj, offset, newValue);
203         }
204
205         public V get(T obj) {
206             if (!tclass.isInstance(obj))
207                 throw new ClassCastException JavaDoc();
208         if (cclass != null)
209             ensureProtectedAccess(obj);
210             return (V)unsafe.getObjectVolatile(obj, offset);
211         }
212
213     private void ensureProtectedAccess(T obj) {
214         if (cclass.isInstance(obj)) {
215         return;
216         }
217         throw new RuntimeException JavaDoc (
218                 new IllegalAccessException JavaDoc("Class " +
219             cclass.getName() +
220                     " can not access a protected member of class " +
221                     tclass.getName() +
222             " using an instance of " +
223                     obj.getClass().getName()
224         )
225         );
226     }
227     }
228 }
229
230
Popular Tags