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/] [AtomicLongFieldUpdater.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 long</tt> fields of designated classes.
14
 * This class is designed for use in atomic data structures in which
15
 * several fields of the same node are independently subject to atomic
16
 * updates.
17
 *
18
 * <p>Note that the guarantees of the {@code compareAndSet}
19
 * method in this class are weaker than in other atomic classes.
20
 * Because this class cannot ensure that all uses of the field
21
 * are appropriate for purposes of atomic access, it can
22
 * guarantee atomicity only with respect to other invocations of
23
 * {@code compareAndSet} and {@code set} on the same updater.
24
 *
25
 * @since 1.5
26
 * @author Doug Lea
27
 * @param <T> The type of the object holding the updatable field
28
 */
29
public abstract class  AtomicLongFieldUpdater<T>  {
30
    /**
31
     * Creates and returns an updater for objects with the given field.
32
     * The Class argument is needed to check that reflective types and
33
     * generic types match.
34
     *
35
     * @param tclass the class of the objects holding the field
36
     * @param fieldName the name of the field to be updated.
37
     * @return the updater
38
     * @throws IllegalArgumentException if the field is not a
39
     * volatile long type.
40
     * @throws RuntimeException with a nested reflection-based
41
     * exception if the class does not hold field or is the wrong type.
42
     */
43
    public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
44
        if (AtomicLong.VM_SUPPORTS_LONG_CAS)
45
            return new CASUpdater<U>(tclass, fieldName);
46
        else
47
            return new LockedUpdater<U>(tclass, fieldName);
48
    }
49
 
50
    /**
51
     * Protected do-nothing constructor for use by subclasses.
52
     */
53
    protected AtomicLongFieldUpdater() {
54
    }
55
 
56
    /**
57
     * Atomically sets the field of the given object managed by this updater
58
     * to the given updated value if the current value <tt>==</tt> the
59
     * expected value. This method is guaranteed to be atomic with respect to
60
     * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
61
     * necessarily with respect to other changes in the field.
62
     *
63
     * @param obj An object whose field to conditionally set
64
     * @param expect the expected value
65
     * @param update the new value
66
     * @return true if successful.
67
     * @throws ClassCastException if <tt>obj</tt> is not an instance
68
     * of the class possessing the field established in the constructor.
69
     */
70
    public abstract boolean compareAndSet(T obj, long expect, long update);
71
 
72
    /**
73
     * Atomically sets the field of the given object managed by this updater
74
     * to the given updated value if the current value <tt>==</tt> the
75
     * expected value. This method is guaranteed to be atomic with respect to
76
     * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
77
     * necessarily with respect to other changes in the field.
78
     * May fail spuriously and does not provide ordering guarantees,
79
     * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
80
     *
81
     * @param obj An object whose field to conditionally set
82
     * @param expect the expected value
83
     * @param update the new value
84
     * @return true if successful.
85
     * @throws ClassCastException if <tt>obj</tt> is not an instance
86
     * of the class possessing the field established in the constructor.
87
     */
88
    public abstract boolean weakCompareAndSet(T obj, long expect, long update);
89
 
90
    /**
91
     * Sets the field of the given object managed by this updater to the
92
     * given updated value. This operation is guaranteed to act as a volatile
93
     * store with respect to subsequent invocations of
94
     * <tt>compareAndSet</tt>.
95
     *
96
     * @param obj An object whose field to set
97
     * @param newValue the new value
98
     */
99
    public abstract void set(T obj, long newValue);
100
 
101
    /**
102
     * Eventually sets the field of the given object managed by this
103
     * updater to the given updated value.
104
     *
105
     * @param obj An object whose field to set
106
     * @param newValue the new value
107
     * @since 1.6
108
     */
109
    public abstract void lazySet(T obj, long newValue);
110
 
111
    /**
112
     * Gets the current value held in the field of the given object managed
113
     * by this updater.
114
     *
115
     * @param obj An object whose field to get
116
     * @return the current value
117
     */
118
    public abstract long get(T obj);
119
 
120
    /**
121
     * Atomically sets the field of the given object managed by this updater
122
     * to the given value and returns the old value.
123
     *
124
     * @param obj An object whose field to get and set
125
     * @param newValue the new value
126
     * @return the previous value
127
     */
128
    public long getAndSet(T obj, long newValue) {
129
        for (;;) {
130
            long current = get(obj);
131
            if (compareAndSet(obj, current, newValue))
132
                return current;
133
        }
134
    }
135
 
136
    /**
137
     * Atomically increments by one the current value of the field of the
138
     * given object managed by this updater.
139
     *
140
     * @param obj An object whose field to get and set
141
     * @return the previous value
142
     */
143
    public long getAndIncrement(T obj) {
144
        for (;;) {
145
            long current = get(obj);
146
            long next = current + 1;
147
            if (compareAndSet(obj, current, next))
148
                return current;
149
        }
150
    }
151
 
152
    /**
153
     * Atomically decrements by one the current value of the field of the
154
     * given object managed by this updater.
155
     *
156
     * @param obj An object whose field to get and set
157
     * @return the previous value
158
     */
159
    public long getAndDecrement(T obj) {
160
        for (;;) {
161
            long current = get(obj);
162
            long next = current - 1;
163
            if (compareAndSet(obj, current, next))
164
                return current;
165
        }
166
    }
167
 
168
    /**
169
     * Atomically adds the given value to the current value of the field of
170
     * the given object managed by this updater.
171
     *
172
     * @param obj An object whose field to get and set
173
     * @param delta the value to add
174
     * @return the previous value
175
     */
176
    public long getAndAdd(T obj, long delta) {
177
        for (;;) {
178
            long current = get(obj);
179
            long next = current + delta;
180
            if (compareAndSet(obj, current, next))
181
                return current;
182
        }
183
    }
184
 
185
    /**
186
     * Atomically increments by one the current value of the field of the
187
     * given object managed by this updater.
188
     *
189
     * @param obj An object whose field to get and set
190
     * @return the updated value
191
     */
192
    public long incrementAndGet(T obj) {
193
        for (;;) {
194
            long current = get(obj);
195
            long next = current + 1;
196
            if (compareAndSet(obj, current, next))
197
                return next;
198
        }
199
    }
200
 
201
    /**
202
     * Atomically decrements by one the current value of the field of the
203
     * given object managed by this updater.
204
     *
205
     * @param obj An object whose field to get and set
206
     * @return the updated value
207
     */
208
    public long decrementAndGet(T obj) {
209
        for (;;) {
210
            long current = get(obj);
211
            long next = current - 1;
212
            if (compareAndSet(obj, current, next))
213
                return next;
214
        }
215
    }
216
 
217
    /**
218
     * Atomically adds the given value to the current value of the field of
219
     * the given object managed by this updater.
220
     *
221
     * @param obj An object whose field to get and set
222
     * @param delta the value to add
223
     * @return the updated value
224
     */
225
    public long addAndGet(T obj, long delta) {
226
        for (;;) {
227
            long current = get(obj);
228
            long next = current + delta;
229
            if (compareAndSet(obj, current, next))
230
                return next;
231
        }
232
    }
233
 
234
    private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
235
        private static final Unsafe unsafe = Unsafe.getUnsafe();
236
        private final long offset;
237
        private final Class<T> tclass;
238
        private final Class cclass;
239
 
240
        CASUpdater(Class<T> tclass, String fieldName) {
241
            Field field = null;
242
            Class caller = null;
243
            int modifiers = 0;
244
            try {
245
                field = tclass.getDeclaredField(fieldName);
246
                caller = sun.reflect.Reflection.getCallerClass(3);
247
                modifiers = field.getModifiers();
248
                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
249
                    caller, tclass, null, modifiers);
250
                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
251
            } catch(Exception ex) {
252
                throw new RuntimeException(ex);
253
            }
254
 
255
            Class fieldt = field.getType();
256
            if (fieldt != long.class)
257
                throw new IllegalArgumentException("Must be long type");
258
 
259
            if (!Modifier.isVolatile(modifiers))
260
                throw new IllegalArgumentException("Must be volatile type");
261
 
262
            this.cclass = (Modifier.isProtected(modifiers) &&
263
                           caller != tclass) ? caller : null;
264
            this.tclass = tclass;
265
            offset = unsafe.objectFieldOffset(field);
266
        }
267
 
268
        private void fullCheck(T obj) {
269
            if (!tclass.isInstance(obj))
270
                throw new ClassCastException();
271
            if (cclass != null)
272
                ensureProtectedAccess(obj);
273
        }
274
 
275
        public boolean compareAndSet(T obj, long expect, long update) {
276
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
277
            return unsafe.compareAndSwapLong(obj, offset, expect, update);
278
        }
279
 
280
        public boolean weakCompareAndSet(T obj, long expect, long update) {
281
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
282
            return unsafe.compareAndSwapLong(obj, offset, expect, update);
283
        }
284
 
285
        public void set(T obj, long newValue) {
286
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
287
            unsafe.putLongVolatile(obj, offset, newValue);
288
        }
289
 
290
        public void lazySet(T obj, long newValue) {
291
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
292
            unsafe.putOrderedLong(obj, offset, newValue);
293
        }
294
 
295
        public long get(T obj) {
296
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
297
            return unsafe.getLongVolatile(obj, offset);
298
        }
299
 
300
        private void ensureProtectedAccess(T obj) {
301
            if (cclass.isInstance(obj)) {
302
                return;
303
            }
304
            throw new RuntimeException (
305
                new IllegalAccessException("Class " +
306
                    cclass.getName() +
307
                    " can not access a protected member of class " +
308
                    tclass.getName() +
309
                    " using an instance of " +
310
                    obj.getClass().getName()
311
                )
312
            );
313
        }
314
    }
315
 
316
 
317
    private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
318
        private static final Unsafe unsafe = Unsafe.getUnsafe();
319
        private final long offset;
320
        private final Class<T> tclass;
321
        private final Class cclass;
322
 
323
        LockedUpdater(Class<T> tclass, String fieldName) {
324
            Field field = null;
325
            Class caller = null;
326
            int modifiers = 0;
327
            try {
328
                field = tclass.getDeclaredField(fieldName);
329
                caller = sun.reflect.Reflection.getCallerClass(3);
330
                modifiers = field.getModifiers();
331
                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
332
                    caller, tclass, null, modifiers);
333
                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
334
            } catch(Exception ex) {
335
                throw new RuntimeException(ex);
336
            }
337
 
338
            Class fieldt = field.getType();
339
            if (fieldt != long.class)
340
                throw new IllegalArgumentException("Must be long type");
341
 
342
            if (!Modifier.isVolatile(modifiers))
343
                throw new IllegalArgumentException("Must be volatile type");
344
 
345
            this.cclass = (Modifier.isProtected(modifiers) &&
346
                           caller != tclass) ? caller : null;
347
            this.tclass = tclass;
348
            offset = unsafe.objectFieldOffset(field);
349
        }
350
 
351
        private void fullCheck(T obj) {
352
            if (!tclass.isInstance(obj))
353
                throw new ClassCastException();
354
            if (cclass != null)
355
                ensureProtectedAccess(obj);
356
        }
357
 
358
        public boolean compareAndSet(T obj, long expect, long update) {
359
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
360
            synchronized(this) {
361
                long v = unsafe.getLong(obj, offset);
362
                if (v != expect)
363
                    return false;
364
                unsafe.putLong(obj, offset, update);
365
                return true;
366
            }
367
        }
368
 
369
        public boolean weakCompareAndSet(T obj, long expect, long update) {
370
            return compareAndSet(obj, expect, update);
371
        }
372
 
373
        public void set(T obj, long newValue) {
374
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
375
            synchronized(this) {
376
                unsafe.putLong(obj, offset, newValue);
377
            }
378
        }
379
 
380
        public void lazySet(T obj, long newValue) {
381
            set(obj, newValue);
382
        }
383
 
384
        public long get(T obj) {
385
            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
386
            synchronized(this) {
387
                return unsafe.getLong(obj, offset);
388
            }
389
        }
390
 
391
        private void ensureProtectedAccess(T obj) {
392
            if (cclass.isInstance(obj)) {
393
                return;
394
            }
395
            throw new RuntimeException (
396
                new IllegalAccessException("Class " +
397
                    cclass.getName() +
398
                    " can not access a protected member of class " +
399
                    tclass.getName() +
400
                    " using an instance of " +
401
                    obj.getClass().getName()
402
                )
403
            );
404
        }
405
    }
406
}

powered by: WebSVN 2.1.0

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