diff options
Diffstat (limited to 'platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java')
-rw-r--r-- | platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java b/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java index 4a885fa5cb5a..fbac0f06cd39 100644 --- a/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java +++ b/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,34 +22,26 @@ */ package com.intellij.util.concurrency; +import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; import sun.misc.Unsafe; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +/** + * Utility class similar to {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater} except: + * - removed access check in getAndSet() hot path for performance + * - new methods "forFieldXXX" added that search by field type instead of field name, which is useful in scrambled classes + */ public class AtomicFieldUpdater<T,V> { private static final Unsafe unsafe = getUnsafe(); @NotNull public static Unsafe getUnsafe() { - Unsafe unsafe = null; - Class uc = Unsafe.class; - try { - Field[] fields = uc.getDeclaredFields(); - for (Field field : fields) { - if (field.getName().equals("theUnsafe")) { - field.setAccessible(true); - unsafe = (Unsafe)field.get(uc); - break; - } - } - } - catch (Exception e) { - throw new RuntimeException(e); - } + Unsafe unsafe = ReflectionUtil.getField(Unsafe.class, null, Unsafe.class, "theUnsafe"); if (unsafe == null) { - throw new RuntimeException("Could not find 'theUnsafe' field in the " + uc); + throw new RuntimeException("Could not find 'theUnsafe' field in the " + Unsafe.class); } return unsafe; } @@ -62,11 +54,22 @@ public class AtomicFieldUpdater<T,V> { } @NotNull - public static <T> AtomicFieldUpdater<T, Long> forLongField(@NotNull Class<T> ownerClass) { + public static <T> AtomicFieldUpdater<T, Long> forLongFieldIn(@NotNull Class<T> ownerClass) { return new AtomicFieldUpdater<T, Long>(ownerClass, long.class); } + @NotNull + public static <T> AtomicFieldUpdater<T, Integer> forIntFieldIn(@NotNull Class<T> ownerClass) { + return new AtomicFieldUpdater<T, Integer>(ownerClass, int.class); + } + private AtomicFieldUpdater(@NotNull Class<T> ownerClass, @NotNull Class<V> fieldType) { + Field found = getTheOnlyVolatileFieldOfClass(ownerClass, fieldType); + offset = unsafe.objectFieldOffset(found); + } + + @NotNull + private static <T,V> Field getTheOnlyVolatileFieldOfClass(@NotNull Class<T> ownerClass, @NotNull Class<V> fieldType) { Field[] declaredFields = ownerClass.getDeclaredFields(); Field found = null; for (Field field : declaredFields) { @@ -89,7 +92,7 @@ public class AtomicFieldUpdater<T,V> { if ((found.getModifiers() & Modifier.VOLATILE) == 0) { throw new IllegalArgumentException("Field "+found+" in the "+ownerClass+" must be volatile"); } - offset = unsafe.objectFieldOffset(found); + return found; } public boolean compareAndSet(@NotNull T owner, V expected, V newValue) { @@ -100,6 +103,10 @@ public class AtomicFieldUpdater<T,V> { return unsafe.compareAndSwapLong(owner, offset, expected, newValue); } + public boolean compareAndSetInt(@NotNull T owner, int expected, int newValue) { + return unsafe.compareAndSwapInt(owner, offset, expected, newValue); + } + public void set(@NotNull T owner, V newValue) { unsafe.putObjectVolatile(owner, offset, newValue); } |