From dc895e391192d28236e876fb592fdaabedacdd74 Mon Sep 17 00:00:00 2001 From: Doug Lea
{@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToWriteLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isWriteLockStamp(stamp))
+ * sl.unlockWrite(stamp);
+ * }}
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * write-lock operation
+ * @since 10
+ */
+ public static boolean isWriteLockStamp(long stamp) {
+ return (stamp & ABITS) == WBIT;
+ }
+
+ /**
+ * Tells whether a stamp represents holding a lock non-exclusively.
+ * This method may be useful in conjunction with
+ * {@link #tryConvertToReadLock}, for example: {@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToReadLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isReadLockStamp(stamp))
+ * sl.unlockRead(stamp);
+ * }}
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * read-lock operation
+ * @since 10
+ */
+ public static boolean isReadLockStamp(long stamp) {
+ return (stamp & RBITS) != 0L;
+ }
+
+ /**
+ * Tells whether a stamp represents holding a lock.
+ * This method may be useful in conjunction with
+ * {@link #tryConvertToReadLock} and {@link #tryConvertToWriteLock},
+ * for example: {@code
+ * long stamp = sl.tryOptimisticRead();
+ * try {
+ * ...
+ * stamp = sl.tryConvertToReadLock(stamp);
+ * ...
+ * stamp = sl.tryConvertToWriteLock(stamp);
+ * ...
+ * } finally {
+ * if (StampedLock.isLockStamp(stamp))
+ * sl.unlock(stamp);
+ * }}
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * read-lock or write-lock operation
+ * @since 10
+ */
+ public static boolean isLockStamp(long stamp) {
+ return (stamp & ABITS) != 0L;
+ }
+
+ /**
+ * Tells whether a stamp represents a successful optimistic read.
+ *
+ * @param stamp a stamp returned by a previous StampedLock operation
+ * @return {@code true} if the stamp was returned by a successful
+ * optimistic read operation, that is, a non-zero return from
+ * {@link #tryOptimisticRead()} or
+ * {@link #tryConvertToOptimisticRead(long)}
+ * @since 10
+ */
+ public static boolean isOptimisticReadStamp(long stamp) {
+ return (stamp & ABITS) == 0L && stamp != 0L;
+ }
+
/**
* Queries the number of read locks held for this lock. This
* method is designed for use in monitoring system state, not for
diff --git a/test/jdk/java/util/concurrent/tck/StampedLockTest.java b/test/jdk/java/util/concurrent/tck/StampedLockTest.java
index 305bfdb5380..e415d470c99 100644
--- a/test/jdk/java/util/concurrent/tck/StampedLockTest.java
+++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java
@@ -35,6 +35,11 @@
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.locks.StampedLock.isLockStamp;
+import static java.util.concurrent.locks.StampedLock.isOptimisticReadStamp;
+import static java.util.concurrent.locks.StampedLock.isReadLockStamp;
+import static java.util.concurrent.locks.StampedLock.isWriteLockStamp;
+
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -1286,11 +1291,115 @@ public class StampedLockTest extends JSR166TestCase {
} while (stamp == 0);
return Math.hypot(currentX, currentY);
}
+
+ double distanceFromOrigin2() {
+ long stamp = sl.tryOptimisticRead();
+ try {
+ retryHoldingLock:
+ for (;; stamp = sl.readLock()) {
+ if (stamp == 0L)
+ continue retryHoldingLock;
+ // possibly racy reads
+ double currentX = x;
+ double currentY = y;
+ if (!sl.validate(stamp))
+ continue retryHoldingLock;
+ return Math.hypot(currentX, currentY);
+ }
+ } finally {
+ if (StampedLock.isReadLockStamp(stamp))
+ sl.unlockRead(stamp);
+ }
+ }
+
+ void moveIfAtOrigin(double newX, double newY) {
+ long stamp = sl.readLock();
+ try {
+ while (x == 0.0 && y == 0.0) {
+ long ws = sl.tryConvertToWriteLock(stamp);
+ if (ws != 0L) {
+ stamp = ws;
+ x = newX;
+ y = newY;
+ return;
+ }
+ else {
+ sl.unlockRead(stamp);
+ stamp = sl.writeLock();
+ }
+ }
+ } finally {
+ sl.unlock(stamp);
+ }
+ }
}
Point p = new Point();
p.move(3.0, 4.0);
assertEquals(5.0, p.distanceFromOrigin());
+ p.moveIfAtOrigin(5.0, 12.0);
+ assertEquals(5.0, p.distanceFromOrigin2());
+ }
+
+ /**
+ * Stamp inspection methods work as expected, and do not inspect
+ * the state of the lock itself.
+ */
+ public void testStampStateInspectionMethods() {
+ StampedLock lock = new StampedLock();
+
+ assertFalse(isWriteLockStamp(0L));
+ assertFalse(isReadLockStamp(0L));
+ assertFalse(isLockStamp(0L));
+ assertFalse(isOptimisticReadStamp(0L));
+
+ {
+ long stamp = lock.writeLock();
+ for (int i = 0; i < 2; i++) {
+ assertTrue(isWriteLockStamp(stamp));
+ assertFalse(isReadLockStamp(stamp));
+ assertTrue(isLockStamp(stamp));
+ assertFalse(isOptimisticReadStamp(stamp));
+ if (i == 0)
+ lock.unlockWrite(stamp);
+ }
+ }
+
+ {
+ long stamp = lock.readLock();
+ for (int i = 0; i < 2; i++) {
+ assertFalse(isWriteLockStamp(stamp));
+ assertTrue(isReadLockStamp(stamp));
+ assertTrue(isLockStamp(stamp));
+ assertFalse(isOptimisticReadStamp(stamp));
+ if (i == 0)
+ lock.unlockRead(stamp);
+ }
+ }
+
+ {
+ long optimisticStamp = lock.tryOptimisticRead();
+ long readStamp = lock.tryConvertToReadLock(optimisticStamp);
+ long writeStamp = lock.tryConvertToWriteLock(readStamp);
+ for (int i = 0; i < 2; i++) {
+ assertFalse(isWriteLockStamp(optimisticStamp));
+ assertFalse(isReadLockStamp(optimisticStamp));
+ assertFalse(isLockStamp(optimisticStamp));
+ assertTrue(isOptimisticReadStamp(optimisticStamp));
+
+ assertFalse(isWriteLockStamp(readStamp));
+ assertTrue(isReadLockStamp(readStamp));
+ assertTrue(isLockStamp(readStamp));
+ assertFalse(isOptimisticReadStamp(readStamp));
+
+ assertTrue(isWriteLockStamp(writeStamp));
+ assertFalse(isReadLockStamp(writeStamp));
+ assertTrue(isLockStamp(writeStamp));
+ assertFalse(isOptimisticReadStamp(writeStamp));
+ if (i == 0)
+ lock.unlockWrite(writeStamp);
+ }
+ }
}
}