summaryrefslogtreecommitdiff
path: root/platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java')
-rw-r--r--platform/util/src/com/intellij/util/concurrency/AtomicFieldUpdater.java45
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);
}