|
29 | 29 | import com.google.common.collect.Lists; |
30 | 30 | import com.google.common.util.concurrent.AbstractFutureBenchmarks.OldAbstractFuture; |
31 | 31 | 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; |
36 | 32 | import java.util.Queue; |
37 | 33 | import java.util.concurrent.ArrayBlockingQueue; |
38 | 34 | import java.util.concurrent.CountDownLatch; |
|
44 | 40 | import java.util.logging.Logger; |
45 | 41 | import org.jspecify.annotations.NullUnmarked; |
46 | 42 | import org.jspecify.annotations.Nullable; |
47 | | -import sun.misc.Unsafe; |
48 | 43 |
|
49 | 44 | /** Benchmarks for {@link ExecutionList}. */ |
50 | 45 | @VmOptions({"-Xms8g", "-Xmx8g"}) |
@@ -85,29 +80,6 @@ public Object getImpl() { |
85 | 80 | }; |
86 | 81 | } |
87 | 82 | }, |
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 | | - }, |
111 | 83 | NEW_WITH_QUEUE { |
112 | 84 | @Override |
113 | 85 | ExecutionListWrapper newExecutionList() { |
@@ -578,127 +550,4 @@ private static final class RunnableExecutorPair { |
578 | 550 | } |
579 | 551 | } |
580 | 552 | } |
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 | | - } |
704 | 553 | } |
0 commit comments