mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
move AtomicFieldUpdater to 11-enabled "concurrency" and port to VarHandle (IDEA-244473 port Collections/Util classes to VarHandles available in JDK 11)
GitOrigin-RevId: 6d01dd54261459f231dfece52305a97985da58db
This commit is contained in:
committed by
intellij-monorepo-bot
parent
858e86bb68
commit
a9742f941a
+6
-3
@@ -44,6 +44,7 @@ import com.intellij.ui.PlaceHolder;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Unit;
|
||||
import kotlin.reflect.full.NoSuchPropertyException;
|
||||
@@ -54,7 +55,8 @@ import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -107,7 +109,7 @@ public final class RemoteExternalSystemCommunicationManager implements ExternalS
|
||||
params.setWorkingDirectory(myWorkingDirectory.isDirectory() ? myWorkingDirectory.getPath() : PathManager.getBinPath());
|
||||
|
||||
// IDE jars.
|
||||
List<String> classPath = new ArrayList<>(PathManager.getUtilClassPath());
|
||||
Collection<String> classPath = new LinkedHashSet<>(PathManager.getUtilClassPath());
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(Project.class)); //intellij.platform.core
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(PlaceHolder.class)); //intellij.platform.editor
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(DependencyScope.class)); //intellij.platform.projectModel
|
||||
@@ -116,6 +118,7 @@ public final class RemoteExternalSystemCommunicationManager implements ExternalS
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(ExtensionPointName.class)); //intellij.platform.extensions
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(StorageUtilKt.class)); //intellij.platform.ide.impl
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(ExternalSystemTaskNotificationListener.class)); //intellij.platform.externalSystem
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(AtomicFieldUpdater.class)); //intellij.platform.concurrency
|
||||
|
||||
// java plugin jar if it's installed
|
||||
Class<? extends SdkType> javaSdkClass = ExternalSystemJdkProvider.getInstance().getJavaSdkType().getClass();
|
||||
@@ -136,7 +139,7 @@ public final class RemoteExternalSystemCommunicationManager implements ExternalS
|
||||
// com.intellij.openapi.externalSystem.model.FSTSerializer dependencies
|
||||
ContainerUtil.addIfNotNull(classPath, PathUtil.getJarPathForClass(ObjectSerializer.class));
|
||||
|
||||
params.getClassPath().addAll(classPath);
|
||||
params.getClassPath().addAll(new ArrayList<>(classPath));
|
||||
|
||||
params.setMainClass(MAIN_CLASS_NAME);
|
||||
params.getVMParametersList().addParametersString("-Djava.awt.headless=true");
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
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 final class AtomicFieldUpdater<ContainingClass, FieldType> {
|
||||
private final VarHandle myHandle;
|
||||
|
||||
public static @NotNull <T, V> AtomicFieldUpdater<T, V> forFieldOfType(@NotNull Class<T> ownerClass, @NotNull Class<V> fieldType) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, fieldType);
|
||||
}
|
||||
|
||||
public static @NotNull <T> AtomicFieldUpdater<T, Long> forLongFieldIn(@NotNull Class<T> ownerClass) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, long.class);
|
||||
}
|
||||
|
||||
public static @NotNull <T> AtomicFieldUpdater<T, Integer> forIntFieldIn(@NotNull Class<T> ownerClass) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, int.class);
|
||||
}
|
||||
|
||||
public static @NotNull <O,E> AtomicFieldUpdater<O, E> forField(@NotNull Field field) {
|
||||
return new AtomicFieldUpdater<>(field);
|
||||
}
|
||||
|
||||
private AtomicFieldUpdater(@NotNull Class<ContainingClass> ownerClass, @NotNull Class<FieldType> fieldType) {
|
||||
this(ReflectionUtil.getTheOnlyVolatileInstanceFieldOfClass(ownerClass, fieldType));
|
||||
}
|
||||
|
||||
private AtomicFieldUpdater(@NotNull Field field) {
|
||||
field.setAccessible(true);
|
||||
if (!Modifier.isVolatile(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalArgumentException(field + " must be volatile instance");
|
||||
}
|
||||
|
||||
try {
|
||||
myHandle = MethodHandles
|
||||
.privateLookupIn(field.getDeclaringClass(), MethodHandles.lookup())
|
||||
.findVarHandle(field.getDeclaringClass(), field.getName(), field.getType());
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean compareAndSet(@NotNull ContainingClass owner, FieldType expected, FieldType newValue) {
|
||||
return (boolean)myHandle.compareAndSet(owner, expected, newValue);
|
||||
}
|
||||
|
||||
public boolean compareAndSetLong(@NotNull ContainingClass owner, long expected, long newValue) {
|
||||
return (boolean)myHandle.compareAndSet(owner, expected, newValue);
|
||||
}
|
||||
|
||||
public boolean compareAndSetInt(@NotNull ContainingClass owner, int expected, int newValue) {
|
||||
return (boolean)myHandle.compareAndSet(owner, expected, newValue);
|
||||
}
|
||||
|
||||
public void setVolatile(@NotNull ContainingClass owner, FieldType newValue) {
|
||||
myHandle.setVolatile(owner, newValue);
|
||||
}
|
||||
|
||||
public FieldType getVolatile(@NotNull ContainingClass owner) {
|
||||
//noinspection unchecked
|
||||
return (FieldType)myHandle.getVolatile(owner);
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
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 final class AtomicFieldUpdater<ContainingClass, FieldType> {
|
||||
private static final Object unsafe;
|
||||
private final long offset;
|
||||
|
||||
private static final MethodHandle compareAndSwapInt;
|
||||
private static final MethodHandle compareAndSwapLong;
|
||||
private static final MethodHandle compareAndSwapObject;
|
||||
private static final MethodHandle putObjectVolatile;
|
||||
private static final MethodHandle getObjectVolatile;
|
||||
|
||||
|
||||
static {
|
||||
unsafe = ReflectionUtil.getUnsafe();
|
||||
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||
try {
|
||||
compareAndSwapInt = lookup.findVirtual(unsafe.getClass(), "compareAndSwapInt", MethodType.methodType(boolean.class, Object.class, long.class, int.class, int.class)).bindTo(unsafe);
|
||||
compareAndSwapLong = lookup.findVirtual(unsafe.getClass(), "compareAndSwapLong", MethodType.methodType(boolean.class, Object.class, long.class, long.class, long.class)).bindTo(unsafe);
|
||||
compareAndSwapObject = lookup.findVirtual(unsafe.getClass(), "compareAndSwapObject", MethodType.methodType(boolean.class, Object.class, long.class, Object.class, Object.class)).bindTo(unsafe);
|
||||
putObjectVolatile = lookup.findVirtual(unsafe.getClass(), "putObjectVolatile", MethodType.methodType(void.class, Object.class, long.class, Object.class)).bindTo(unsafe);
|
||||
getObjectVolatile = lookup.findVirtual(unsafe.getClass(), "getObjectVolatile", MethodType.methodType(Object.class, Object.class, long.class)).bindTo(unsafe);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull <T, V> AtomicFieldUpdater<T, V> forFieldOfType(@NotNull Class<T> ownerClass, @NotNull Class<V> fieldType) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, fieldType);
|
||||
}
|
||||
|
||||
public static @NotNull <T> AtomicFieldUpdater<T, Long> forLongFieldIn(@NotNull Class<T> ownerClass) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, long.class);
|
||||
}
|
||||
|
||||
public static @NotNull <T> AtomicFieldUpdater<T, Integer> forIntFieldIn(@NotNull Class<T> ownerClass) {
|
||||
return new AtomicFieldUpdater<>(ownerClass, int.class);
|
||||
}
|
||||
|
||||
public static @NotNull <O,E> AtomicFieldUpdater<O, E> forField(@NotNull Field field) {
|
||||
return new AtomicFieldUpdater<>(field);
|
||||
}
|
||||
|
||||
private AtomicFieldUpdater(@NotNull Class<ContainingClass> ownerClass, @NotNull Class<FieldType> fieldType) {
|
||||
this(ReflectionUtil.getTheOnlyVolatileInstanceFieldOfClass(ownerClass, fieldType));
|
||||
}
|
||||
|
||||
private AtomicFieldUpdater(@NotNull Field field) {
|
||||
field.setAccessible(true);
|
||||
if (!Modifier.isVolatile(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) throw new IllegalArgumentException(field + " must be volatile instance");
|
||||
try {
|
||||
MethodHandle objectFieldOffset =
|
||||
MethodHandles.publicLookup().findVirtual(unsafe.getClass(), "objectFieldOffset", MethodType.methodType(long.class, Field.class));
|
||||
offset = (long)objectFieldOffset.invoke(unsafe, field);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean compareAndSet(@NotNull ContainingClass owner, FieldType expected, FieldType newValue) {
|
||||
try {
|
||||
return (boolean)compareAndSwapObject.invokeExact(owner, offset, expected, newValue);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean compareAndSetLong(@NotNull ContainingClass owner, long expected, long newValue) {
|
||||
try {
|
||||
return (boolean)compareAndSwapLong.invokeExact(owner, offset, expected, newValue);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean compareAndSetInt(@NotNull ContainingClass owner, int expected, int newValue) {
|
||||
try {
|
||||
return (boolean)compareAndSwapInt.invokeExact(owner, offset, expected, newValue);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVolatile(@NotNull ContainingClass owner, FieldType newValue) {
|
||||
try {
|
||||
putObjectVolatile.invokeExact(owner, offset, newValue);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public FieldType getVolatile(@NotNull ContainingClass owner) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (FieldType)getObjectVolatile.invokeExact(owner, offset);
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user