Skip to content

Commit 80aab00

Browse files
cpovirkGoogle Java Core Libraries
authored and
Google Java Core Libraries
committed
Remove Unsafe-based implementation from ExecutionListBenchmark.
It's nice to have, but it's not worth going to any trouble for in the face of the ongoing work to remove the `Unsafe` APIs. RELNOTES=n/a PiperOrigin-RevId: 714178045
1 parent b3bb29a commit 80aab00

File tree

2 files changed

+0
-302
lines changed

2 files changed

+0
-302
lines changed

android/guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java

-151
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@
2929
import com.google.common.collect.Lists;
3030
import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture;
3131
import com.google.errorprone.annotations.concurrent.GuardedBy;
32-
import java.lang.reflect.Field;
33-
import java.security.AccessController;
34-
import java.security.PrivilegedActionException;
35-
import java.security.PrivilegedExceptionAction;
3632
import java.util.Queue;
3733
import java.util.concurrent.ArrayBlockingQueue;
3834
import java.util.concurrent.CountDownLatch;
@@ -44,7 +40,6 @@
4440
import java.util.logging.Logger;
4541
import org.jspecify.annotations.NullUnmarked;
4642
import org.jspecify.annotations.Nullable;
47-
import sun.misc.Unsafe;
4843

4944
/** Benchmarks for {@link ExecutionList}. */
5045
@VmOptions({"-Xms8g", "-Xmx8g"})
@@ -85,29 +80,6 @@ public Object getImpl() {
8580
};
8681
}
8782
},
88-
NEW_WITH_CAS {
89-
@Override
90-
ExecutionListWrapper newExecutionList() {
91-
return new ExecutionListWrapper() {
92-
final ExecutionListUsingCompareAndSwap list = new ExecutionListUsingCompareAndSwap();
93-
94-
@Override
95-
public void add(Runnable runnable, Executor executor) {
96-
list.add(runnable, executor);
97-
}
98-
99-
@Override
100-
public void execute() {
101-
list.execute();
102-
}
103-
104-
@Override
105-
public Object getImpl() {
106-
return list;
107-
}
108-
};
109-
}
110-
},
11183
NEW_WITH_QUEUE {
11284
@Override
11385
ExecutionListWrapper newExecutionList() {
@@ -578,127 +550,4 @@ private static final class RunnableExecutorPair {
578550
}
579551
}
580552
}
581-
582-
// A version of the list that uses compare and swap to manage the stack without locks.
583-
@SuppressWarnings({"SunApi", "removal"}) // b/345822163
584-
private static final class ExecutionListUsingCompareAndSwap {
585-
static final Logger log = Logger.getLogger(ExecutionListUsingCompareAndSwap.class.getName());
586-
587-
private static final Unsafe UNSAFE;
588-
private static final long HEAD_OFFSET;
589-
590-
/**
591-
* A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the
592-
* bottom of the stack.
593-
*/
594-
private static final RunnableExecutorPair NULL_PAIR = new RunnableExecutorPair(null, null);
595-
596-
static {
597-
try {
598-
UNSAFE = getUnsafe();
599-
HEAD_OFFSET =
600-
UNSAFE.objectFieldOffset(
601-
ExecutionListUsingCompareAndSwap.class.getDeclaredField("head"));
602-
} catch (Exception ex) {
603-
throw new Error(ex);
604-
}
605-
}
606-
607-
/** TODO(lukes): This was copied verbatim from Striped64.java... standardize this? */
608-
private static Unsafe getUnsafe() {
609-
try {
610-
return Unsafe.getUnsafe();
611-
} catch (SecurityException tryReflectionInstead) {
612-
}
613-
try {
614-
return AccessController.doPrivileged(
615-
new PrivilegedExceptionAction<Unsafe>() {
616-
@Override
617-
public Unsafe run() throws Exception {
618-
Class<Unsafe> k = Unsafe.class;
619-
for (Field f : k.getDeclaredFields()) {
620-
f.setAccessible(true);
621-
Object x = f.get(null);
622-
if (k.isInstance(x)) return k.cast(x);
623-
}
624-
throw new NoSuchFieldError("the Unsafe");
625-
}
626-
});
627-
} catch (PrivilegedActionException e) {
628-
throw new RuntimeException("Could not initialize intrinsics", e.getCause());
629-
}
630-
}
631-
632-
private volatile RunnableExecutorPair head = NULL_PAIR;
633-
634-
public void add(Runnable runnable, Executor executor) {
635-
Preconditions.checkNotNull(runnable, "Runnable was null.");
636-
Preconditions.checkNotNull(executor, "Executor was null.");
637-
638-
RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor);
639-
RunnableExecutorPair oldHead;
640-
do {
641-
oldHead = head;
642-
if (oldHead == null) {
643-
// If runnables == null then execute() has been called so we should just execute our
644-
// listener immediately.
645-
newHead.execute();
646-
return;
647-
}
648-
// Try to make newHead the new head of the stack at runnables.
649-
newHead.next = oldHead;
650-
} while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, oldHead, newHead));
651-
}
652-
653-
public void execute() {
654-
RunnableExecutorPair stack;
655-
do {
656-
stack = head;
657-
if (stack == null) {
658-
// If head == null then execute() has been called so we should just return
659-
return;
660-
}
661-
// try to swap null into head.
662-
} while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null));
663-
664-
RunnableExecutorPair reversedStack = null;
665-
while (stack != NULL_PAIR) {
666-
RunnableExecutorPair head = stack;
667-
stack = stack.next;
668-
head.next = reversedStack;
669-
reversedStack = head;
670-
}
671-
stack = reversedStack;
672-
while (stack != null) {
673-
stack.execute();
674-
stack = stack.next;
675-
}
676-
}
677-
678-
private static class RunnableExecutorPair {
679-
final Runnable runnable;
680-
final Executor executor;
681-
// Volatile because this is written on one thread and read on another with no synchronization.
682-
@Nullable volatile RunnableExecutorPair next;
683-
684-
RunnableExecutorPair(@Nullable Runnable runnable, @Nullable Executor executor) {
685-
this.runnable = runnable;
686-
this.executor = executor;
687-
}
688-
689-
void execute() {
690-
try {
691-
executor.execute(runnable);
692-
} catch (RuntimeException e) {
693-
log.log(
694-
Level.SEVERE,
695-
"RuntimeException while executing runnable "
696-
+ runnable
697-
+ " with executor "
698-
+ executor,
699-
e);
700-
}
701-
}
702-
}
703-
}
704553
}

guava-tests/benchmark/com/google/common/util/concurrent/ExecutionListBenchmark.java

-151
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@
2929
import com.google.common.collect.Lists;
3030
import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture;
3131
import com.google.errorprone.annotations.concurrent.GuardedBy;
32-
import java.lang.reflect.Field;
33-
import java.security.AccessController;
34-
import java.security.PrivilegedActionException;
35-
import java.security.PrivilegedExceptionAction;
3632
import java.util.Queue;
3733
import java.util.concurrent.ArrayBlockingQueue;
3834
import java.util.concurrent.CountDownLatch;
@@ -44,7 +40,6 @@
4440
import java.util.logging.Logger;
4541
import org.jspecify.annotations.NullUnmarked;
4642
import org.jspecify.annotations.Nullable;
47-
import sun.misc.Unsafe;
4843

4944
/** Benchmarks for {@link ExecutionList}. */
5045
@VmOptions({"-Xms8g", "-Xmx8g"})
@@ -85,29 +80,6 @@ public Object getImpl() {
8580
};
8681
}
8782
},
88-
NEW_WITH_CAS {
89-
@Override
90-
ExecutionListWrapper newExecutionList() {
91-
return new ExecutionListWrapper() {
92-
final ExecutionListUsingCompareAndSwap list = new ExecutionListUsingCompareAndSwap();
93-
94-
@Override
95-
public void add(Runnable runnable, Executor executor) {
96-
list.add(runnable, executor);
97-
}
98-
99-
@Override
100-
public void execute() {
101-
list.execute();
102-
}
103-
104-
@Override
105-
public Object getImpl() {
106-
return list;
107-
}
108-
};
109-
}
110-
},
11183
NEW_WITH_QUEUE {
11284
@Override
11385
ExecutionListWrapper newExecutionList() {
@@ -578,127 +550,4 @@ private static final class RunnableExecutorPair {
578550
}
579551
}
580552
}
581-
582-
// A version of the list that uses compare and swap to manage the stack without locks.
583-
@SuppressWarnings({"SunApi", "removal"}) // b/345822163
584-
private static final class ExecutionListUsingCompareAndSwap {
585-
static final Logger log = Logger.getLogger(ExecutionListUsingCompareAndSwap.class.getName());
586-
587-
private static final Unsafe UNSAFE;
588-
private static final long HEAD_OFFSET;
589-
590-
/**
591-
* A special instance of {@link RunnableExecutorPair} that is used as a sentinel value for the
592-
* bottom of the stack.
593-
*/
594-
private static final RunnableExecutorPair NULL_PAIR = new RunnableExecutorPair(null, null);
595-
596-
static {
597-
try {
598-
UNSAFE = getUnsafe();
599-
HEAD_OFFSET =
600-
UNSAFE.objectFieldOffset(
601-
ExecutionListUsingCompareAndSwap.class.getDeclaredField("head"));
602-
} catch (Exception ex) {
603-
throw new Error(ex);
604-
}
605-
}
606-
607-
/** TODO(lukes): This was copied verbatim from Striped64.java... standardize this? */
608-
private static Unsafe getUnsafe() {
609-
try {
610-
return Unsafe.getUnsafe();
611-
} catch (SecurityException tryReflectionInstead) {
612-
}
613-
try {
614-
return AccessController.doPrivileged(
615-
new PrivilegedExceptionAction<Unsafe>() {
616-
@Override
617-
public Unsafe run() throws Exception {
618-
Class<Unsafe> k = Unsafe.class;
619-
for (Field f : k.getDeclaredFields()) {
620-
f.setAccessible(true);
621-
Object x = f.get(null);
622-
if (k.isInstance(x)) return k.cast(x);
623-
}
624-
throw new NoSuchFieldError("the Unsafe");
625-
}
626-
});
627-
} catch (PrivilegedActionException e) {
628-
throw new RuntimeException("Could not initialize intrinsics", e.getCause());
629-
}
630-
}
631-
632-
private volatile RunnableExecutorPair head = NULL_PAIR;
633-
634-
public void add(Runnable runnable, Executor executor) {
635-
Preconditions.checkNotNull(runnable, "Runnable was null.");
636-
Preconditions.checkNotNull(executor, "Executor was null.");
637-
638-
RunnableExecutorPair newHead = new RunnableExecutorPair(runnable, executor);
639-
RunnableExecutorPair oldHead;
640-
do {
641-
oldHead = head;
642-
if (oldHead == null) {
643-
// If runnables == null then execute() has been called so we should just execute our
644-
// listener immediately.
645-
newHead.execute();
646-
return;
647-
}
648-
// Try to make newHead the new head of the stack at runnables.
649-
newHead.next = oldHead;
650-
} while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, oldHead, newHead));
651-
}
652-
653-
public void execute() {
654-
RunnableExecutorPair stack;
655-
do {
656-
stack = head;
657-
if (stack == null) {
658-
// If head == null then execute() has been called so we should just return
659-
return;
660-
}
661-
// try to swap null into head.
662-
} while (!UNSAFE.compareAndSwapObject(this, HEAD_OFFSET, stack, null));
663-
664-
RunnableExecutorPair reversedStack = null;
665-
while (stack != NULL_PAIR) {
666-
RunnableExecutorPair head = stack;
667-
stack = stack.next;
668-
head.next = reversedStack;
669-
reversedStack = head;
670-
}
671-
stack = reversedStack;
672-
while (stack != null) {
673-
stack.execute();
674-
stack = stack.next;
675-
}
676-
}
677-
678-
private static class RunnableExecutorPair {
679-
final Runnable runnable;
680-
final Executor executor;
681-
// Volatile because this is written on one thread and read on another with no synchronization.
682-
@Nullable volatile RunnableExecutorPair next;
683-
684-
RunnableExecutorPair(@Nullable Runnable runnable, @Nullable Executor executor) {
685-
this.runnable = runnable;
686-
this.executor = executor;
687-
}
688-
689-
void execute() {
690-
try {
691-
executor.execute(runnable);
692-
} catch (RuntimeException e) {
693-
log.log(
694-
Level.SEVERE,
695-
"RuntimeException while executing runnable "
696-
+ runnable
697-
+ " with executor "
698-
+ executor,
699-
e);
700-
}
701-
}
702-
}
703-
}
704553
}

0 commit comments

Comments
 (0)