+ /**
+ * This updater is used to manipulate the "ready" transaction. We perform only atomic
+ * get-and-set on it.
+ */
+ private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> READY_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "readyTx");
+ @SuppressWarnings("unused") // Accessed via READY_UPDATER
+ private volatile PingPongTransaction readyTx;
+
+ /**
+ * This updater is used to manipulate the "locked" transaction. A locked transaction
+ * means we know that the user still holds a transaction and should at some point call
+ * us. We perform on compare-and-swap to ensure we properly detect when a user is
+ * attempting to allocated multiple transactions concurrently.
+ */
+ private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> LOCKED_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "lockedTx");
+ private volatile PingPongTransaction lockedTx;
+