26
26
import com .google .common .annotations .GwtCompatible ;
27
27
import com .google .common .util .concurrent .AbstractFuture .Listener ;
28
28
import com .google .common .util .concurrent .internal .InternalFutureFailureAccess ;
29
+ import com .google .errorprone .annotations .ThreadSafe ;
29
30
import com .google .j2objc .annotations .J2ObjCIncompatible ;
30
31
import com .google .j2objc .annotations .ReflectionSupport ;
31
32
import com .google .j2objc .annotations .RetainedLocalRef ;
@@ -388,6 +389,22 @@ void unpark() {
388
389
389
390
// TODO(lukes): Investigate using a @Contended annotation on these fields once one is available.
390
391
392
+ /*
393
+ * The following fields are package-private, even though we intend never to use them outside this
394
+ * file. If they were instead private, then we wouldn't be able to access them reflectively from
395
+ * within VarHandleAtomicHelper.
396
+ *
397
+ * Package-private "shouldn't" be necessary: VarHandleAtomicHelper and AbstractFutureState
398
+ * "should" be nestmates, so a call to MethodHandles.lookup inside VarHandleAtomicHelper "should"
399
+ * have access to AbstractFutureState's private fields. However, our open-source build uses
400
+ * `-source 8 -target 8`, so the class files from that build can't express nestmates. Thus, when
401
+ * those class files are used from Java 9 or higher (i.e., high enough to trigger the VarHandle
402
+ * code path), such a lookup would fail with an IllegalAccessException.
403
+ *
404
+ * This same problem is one of the reasons for us to likewise keep the fields in Waiter as
405
+ * package-private instead of private.
406
+ */
407
+
391
408
/**
392
409
* This field encodes the current state of the future.
393
410
*
@@ -403,13 +420,13 @@ void unpark() {
403
420
* argument.
404
421
* </ul>
405
422
*/
406
- private volatile @ Nullable Object valueField ;
423
+ @ ThreadSafe . Suppress volatile @ Nullable Object valueField ;
407
424
408
425
/** All listeners. */
409
- private volatile @ Nullable Listener listenersField ;
426
+ @ ThreadSafe . Suppress volatile @ Nullable Listener listenersField ;
410
427
411
428
/** All waiting threads. */
412
- private volatile @ Nullable Waiter waitersField ;
429
+ @ ThreadSafe . Suppress volatile @ Nullable Waiter waitersField ;
413
430
414
431
/** Non-volatile write of the thread to the {@link Waiter#thread} field. */
415
432
private static void putThread (Waiter waiter , Thread newValue ) {
@@ -553,7 +570,7 @@ private static final class VarHandleAtomicHelper extends AtomicHelper {
553
570
static final VarHandle valueUpdater ;
554
571
555
572
static {
556
- MethodHandles .Lookup lookup = methodHandlesLookupFromWithinAbstractFutureState ();
573
+ MethodHandles .Lookup lookup = MethodHandles . lookup ();
557
574
try {
558
575
waiterThreadUpdater = lookup .findVarHandle (Waiter .class , "thread" , Thread .class );
559
576
waiterNextUpdater = lookup .findVarHandle (Waiter .class , "next" , Waiter .class );
@@ -610,28 +627,6 @@ private static LinkageError newLinkageError(Throwable cause) {
610
627
}
611
628
}
612
629
613
- /**
614
- * Returns the result of calling {@link MethodHandles#lookup} from inside {@link
615
- * AbstractFutureState}. By virtue of being created there, it has access to the private fields of
616
- * {@link AbstractFutureState}, so that access is available to anyone who calls this
617
- * method—specifically, to {@link VarHandleAtomicHelper}.
618
- *
619
- * <p>This "shouldn't" be necessary: {@link VarHandleAtomicHelper} and {@link AbstractFutureState}
620
- * "should" be nestmates, so a call to {@link MethodHandles#lookup} inside {@link
621
- * VarHandleAtomicHelper} "should" have access to each other's private fields. However, our
622
- * open-source build uses {@code -source 8 -target 8}, so the class files from that build can't
623
- * express nestmates. Thus, when those class files are used from Java 9 or higher (i.e., high
624
- * enough to trigger the {@link VarHandle} code path), such a lookup would fail with an {@link
625
- * IllegalAccessException}.
626
- *
627
- * <p>Note that we do not have a similar problem with the fields in {@link Waiter} because those
628
- * fields are not private. (We could solve the problem with {@link AbstractFutureState} fields in
629
- * the same way if we wanted.)
630
- */
631
- private static MethodHandles .Lookup methodHandlesLookupFromWithinAbstractFutureState () {
632
- return MethodHandles .lookup ();
633
- }
634
-
635
630
/**
636
631
* {@link AtomicHelper} based on {@link sun.misc.Unsafe}.
637
632
*
@@ -734,13 +729,13 @@ private static final class AtomicReferenceFieldUpdaterAtomicHelper extends Atomi
734
729
Waiter .class , Waiter .class , "next" );
735
730
private static final AtomicReferenceFieldUpdater <
736
731
? super AbstractFutureState <?>, @ Nullable Waiter >
737
- waitersUpdater = waitersUpdaterFromWithinAbstractFutureState ( );
732
+ waitersUpdater = newUpdater ( AbstractFutureState . class , Waiter . class , "waitersField" );
738
733
private static final AtomicReferenceFieldUpdater <
739
734
? super AbstractFutureState <?>, @ Nullable Listener >
740
- listenersUpdater = listenersUpdaterFromWithinAbstractFutureState ( );
735
+ listenersUpdater = newUpdater ( AbstractFutureState . class , Listener . class , "listenersField" );
741
736
private static final AtomicReferenceFieldUpdater <
742
737
? super AbstractFutureState <?>, @ Nullable Object >
743
- valueUpdater = valueUpdaterFromWithinAbstractFutureState ( );
738
+ valueUpdater = newUpdater ( AbstractFutureState . class , Object . class , "valueField" );
744
739
745
740
@ Override
746
741
void putThread (Waiter waiter , Thread newValue ) {
@@ -780,39 +775,6 @@ boolean casValue(AbstractFutureState<?> future, @Nullable Object expect, Object
780
775
}
781
776
}
782
777
783
- /**
784
- * Returns an {@link AtomicReferenceFieldUpdater} for {@link #waiters}.
785
- *
786
- * <p>The creation of the updater has to happen directly inside {@link AbstractFutureState}, as
787
- * discussed in {@link #methodHandlesLookupFromWithinAbstractFutureState}.
788
- */
789
- private static AtomicReferenceFieldUpdater <? super AbstractFutureState <?>, @ Nullable Waiter >
790
- waitersUpdaterFromWithinAbstractFutureState () {
791
- return newUpdater (AbstractFutureState .class , Waiter .class , "waitersField" );
792
- }
793
-
794
- /**
795
- * Returns an {@link AtomicReferenceFieldUpdater} for {@link #listeners}.
796
- *
797
- * <p>The creation of the updater has to happen directly inside {@link AbstractFutureState}, as
798
- * discussed in {@link #methodHandlesLookupFromWithinAbstractFutureState}.
799
- */
800
- private static AtomicReferenceFieldUpdater <? super AbstractFutureState <?>, @ Nullable Listener >
801
- listenersUpdaterFromWithinAbstractFutureState () {
802
- return newUpdater (AbstractFutureState .class , Listener .class , "listenersField" );
803
- }
804
-
805
- /**
806
- * Returns an {@link AtomicReferenceFieldUpdater} for {@link #value}.
807
- *
808
- * <p>The creation of the updater has to happen directly inside {@link AbstractFutureState}, as
809
- * discussed in {@link #methodHandlesLookupFromWithinAbstractFutureState}.
810
- */
811
- private static AtomicReferenceFieldUpdater <? super AbstractFutureState <?>, @ Nullable Object >
812
- valueUpdaterFromWithinAbstractFutureState () {
813
- return newUpdater (AbstractFutureState .class , Object .class , "valueField" );
814
- }
815
-
816
778
/**
817
779
* {@link AtomicHelper} based on {@code synchronized} and volatile writes.
818
780
*
0 commit comments