OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [external/] [jsr166/] [java/] [util/] [concurrent/] [atomic/] [AtomicReferenceFieldUpdater.java] - Blame information for rev 768

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 768 jeremybenn
/*
2
 * Written by Doug Lea with assistance from members of JCP JSR-166
3
 * Expert Group and released to the public domain, as explained at
4
 * http://creativecommons.org/licenses/publicdomain
5
 */
6
 
7
package java.util.concurrent.atomic;
8
import sun.misc.Unsafe;
9
import java.lang.reflect.*;
10
 
11
/**
12
 * A reflection-based utility that enables atomic updates to
13
 * designated <tt>volatile</tt> reference fields of designated
14
 * classes.  This class is designed for use in atomic data structures
15
 * in which several reference fields of the same node are
16
 * independently subject to atomic updates. For example, a tree node
17
 * might be declared as
18
 *
19
 * <pre>
20
 * class Node {
21
 *   private volatile Node left, right;
22
 *
23
 *   private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
24
 *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
25
 *   private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
26
 *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
27
 *
28
 *   Node getLeft() { return left;  }
29
 *   boolean compareAndSetLeft(Node expect, Node update) {
30
 *     return leftUpdater.compareAndSet(this, expect, update);
31
 *   }
32
 *   // ... and so on
33
 * }
34
 * </pre>
35
 *
36
 * <p>Note that the guarantees of the {@code compareAndSet}
37
 * method in this class are weaker than in other atomic classes.
38
 * Because this class cannot ensure that all uses of the field
39
 * are appropriate for purposes of atomic access, it can
40
 * guarantee atomicity only with respect to other invocations of
41
 * {@code compareAndSet} and {@code set} on the same updater.
42
 *
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 and returns an updater for objects with the given field.
52
     * The Class arguments are needed to check that reflective types and
53
     * generic types match.
54
     *
55
     * @param tclass the class of the objects holding the field.
56
     * @param vclass the class of the field
57
     * @param fieldName the name of the field to be updated.
58
     * @return the updater
59
     * @throws IllegalArgumentException if the field is not a volatile reference type.
60
     * @throws RuntimeException with a nested reflection-based
61
     * exception if the class does not hold field or is the wrong type.
62
     */
63
    public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
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 sets the field of the given object managed by this updater
77
     * to the given updated value if the current value <tt>==</tt> the
78
     * expected value. This method is guaranteed to be atomic with respect to
79
     * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
80
     * necessarily with respect to other changes in the field.
81
     *
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
    public abstract boolean compareAndSet(T obj, V expect, V update);
88
 
89
    /**
90
     * Atomically sets the field of the given object managed by this updater
91
     * to the given updated value if the current value <tt>==</tt> the
92
     * expected value. This method is guaranteed to be atomic with respect to
93
     * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
94
     * necessarily with respect to other changes in the field.
95
     * May fail spuriously and does not provide ordering guarantees,
96
     * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
97
     *
98
     * @param obj An object whose field to conditionally set
99
     * @param expect the expected value
100
     * @param update the new value
101
     * @return true if successful.
102
     */
103
    public abstract boolean weakCompareAndSet(T obj, V expect, V update);
104
 
105
    /**
106
     * Sets the field of the given object managed by this updater to the
107
     * given updated value. This operation is guaranteed to act as a volatile
108
     * store with respect to subsequent invocations of
109
     * <tt>compareAndSet</tt>.
110
     *
111
     * @param obj An object whose field to set
112
     * @param newValue the new value
113
     */
114
    public abstract void set(T obj, V newValue);
115
 
116
    /**
117
     * Eventually sets the field of the given object managed by this
118
     * updater to the given updated value.
119
     *
120
     * @param obj An object whose field to set
121
     * @param newValue the new value
122
     * @since 1.6
123
     */
124
    public abstract void lazySet(T obj, V newValue);
125
 
126
    /**
127
     * Gets the current value held in the field of the given object managed
128
     * by this updater.
129
     *
130
     * @param obj An object whose field to get
131
     * @return the current value
132
     */
133
    public abstract V get(T obj);
134
 
135
    /**
136
     * Atomically sets the field of the given object managed by this updater
137
     * to the given value and returns the old value.
138
     *
139
     * @param obj An object whose field to get and set
140
     * @param newValue the new value
141
     * @return the previous value
142
     */
143
    public V getAndSet(T obj, V newValue) {
144
        for (;;) {
145
            V current = get(obj);
146
            if (compareAndSet(obj, current, newValue))
147
                return current;
148
        }
149
    }
150
 
151
    private static final class AtomicReferenceFieldUpdaterImpl<T,V>
152
        extends AtomicReferenceFieldUpdater<T,V> {
153
        private static final Unsafe unsafe = Unsafe.getUnsafe();
154
        private final long offset;
155
        private final Class<T> tclass;
156
        private final Class<V> vclass;
157
        private final Class cclass;
158
 
159
        /*
160
         * Internal type checks within all update methods contain
161
         * internal inlined optimizations checking for the common
162
         * cases where the class is final (in which case a simple
163
         * getClass comparison suffices) or is of type Object (in
164
         * which case no check is needed because all objects are
165
         * instances of Object). The Object case is handled simply by
166
         * setting vclass to null in constructor.  The targetCheck and
167
         * updateCheck methods are invoked when these faster
168
         * screenings fail.
169
         */
170
 
171
        AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
172
                                        Class<V> vclass,
173
                                        String fieldName) {
174
            Field field = null;
175
            Class fieldClass = null;
176
            Class caller = null;
177
            int modifiers = 0;
178
            try {
179
                field = tclass.getDeclaredField(fieldName);
180
                caller = sun.reflect.Reflection.getCallerClass(3);
181
                modifiers = field.getModifiers();
182
                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
183
                    caller, tclass, null, modifiers);
184
                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
185
                fieldClass = field.getType();
186
            } catch (Exception ex) {
187
                throw new RuntimeException(ex);
188
            }
189
 
190
            if (vclass != fieldClass)
191
                throw new ClassCastException();
192
 
193
            if (!Modifier.isVolatile(modifiers))
194
                throw new IllegalArgumentException("Must be volatile type");
195
 
196
            this.cclass = (Modifier.isProtected(modifiers) &&
197
                           caller != tclass) ? caller : null;
198
            this.tclass = tclass;
199
            if (vclass == Object.class)
200
                this.vclass = null;
201
            else
202
                this.vclass = vclass;
203
            offset = unsafe.objectFieldOffset(field);
204
        }
205
 
206
        void targetCheck(T obj) {
207
            if (!tclass.isInstance(obj))
208
                throw new ClassCastException();
209
            if (cclass != null)
210
                ensureProtectedAccess(obj);
211
        }
212
 
213
        void updateCheck(T obj, V update) {
214
            if (!tclass.isInstance(obj) ||
215
                (update != null && vclass != null && !vclass.isInstance(update)))
216
                throw new ClassCastException();
217
            if (cclass != null)
218
                ensureProtectedAccess(obj);
219
        }
220
 
221
        public boolean compareAndSet(T obj, V expect, V update) {
222
            if (obj == null || obj.getClass() != tclass || cclass != null ||
223
                (update != null && vclass != null &&
224
                 vclass != update.getClass()))
225
                updateCheck(obj, update);
226
            return unsafe.compareAndSwapObject(obj, offset, expect, update);
227
        }
228
 
229
        public boolean weakCompareAndSet(T obj, V expect, V update) {
230
            // same implementation as strong form for now
231
            if (obj == null || obj.getClass() != tclass || cclass != null ||
232
                (update != null && vclass != null &&
233
                 vclass != update.getClass()))
234
                updateCheck(obj, update);
235
            return unsafe.compareAndSwapObject(obj, offset, expect, update);
236
        }
237
 
238
        public void set(T obj, V newValue) {
239
            if (obj == null || obj.getClass() != tclass || cclass != null ||
240
                (newValue != null && vclass != null &&
241
                 vclass != newValue.getClass()))
242
                updateCheck(obj, newValue);
243
            unsafe.putObjectVolatile(obj, offset, newValue);
244
        }
245
 
246
        public void lazySet(T obj, V newValue) {
247
            if (obj == null || obj.getClass() != tclass || cclass != null ||
248
                (newValue != null && vclass != null &&
249
                 vclass != newValue.getClass()))
250
                updateCheck(obj, newValue);
251
            unsafe.putOrderedObject(obj, offset, newValue);
252
        }
253
 
254
        public V get(T obj) {
255
            if (obj == null || obj.getClass() != tclass || cclass != null)
256
                targetCheck(obj);
257
            return (V)unsafe.getObjectVolatile(obj, offset);
258
        }
259
 
260
        private void ensureProtectedAccess(T obj) {
261
            if (cclass.isInstance(obj)) {
262
                return;
263
            }
264
            throw new RuntimeException (
265
                new IllegalAccessException("Class " +
266
                    cclass.getName() +
267
                    " can not access a protected member of class " +
268
                    tclass.getName() +
269
                    " using an instance of " +
270
                    obj.getClass().getName()
271
                )
272
            );
273
        }
274
    }
275
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.