ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
(Generate patch)

Comparing jsr166/src/jsr166e/StampedLock.java (file contents):
Revision 1.35 by jsr166, Mon Jan 28 22:22:08 2013 UTC vs.
Revision 1.36 by dl, Wed Jun 19 14:55:40 2013 UTC

# Line 5 | Line 5
5   */
6  
7   package jsr166e;
8
9 import java.util.concurrent.ThreadLocalRandom;
8   import java.util.concurrent.TimeUnit;
9 + import java.util.concurrent.ThreadLocalRandom;
10   import java.util.concurrent.locks.Lock;
11   import java.util.concurrent.locks.Condition;
12   import java.util.concurrent.locks.ReadWriteLock;
# Line 119 | Line 118 | import java.util.concurrent.locks.LockSu
118   *     }
119   *   }
120   *
121 < *   double distanceFromOriginV1() { // A read-only method
122 < *     long stamp;
123 < *     if ((stamp = sl.tryOptimisticRead()) != 0L) { // optimistic
124 < *       double currentX = x;
125 < *       double currentY = y;
126 < *       if (sl.validate(stamp))
127 < *         return Math.sqrt(currentX * currentX + currentY * currentY);
128 < *     }
129 < *     stamp = sl.readLock(); // fall back to read lock
130 < *     try {
131 < *       double currentX = x;
133 < *       double currentY = y;
134 < *         return Math.sqrt(currentX * currentX + currentY * currentY);
135 < *     } finally {
136 < *       sl.unlockRead(stamp);
137 < *     }
138 < *   }
139 < *
140 < *   double distanceFromOriginV2() { // combines code paths
141 < *     double currentX = 0.0, currentY = 0.0;
142 < *     for (long stamp = sl.tryOptimisticRead(); ; stamp = sl.readLock()) {
143 < *       try {
144 < *         currentX = x;
145 < *         currentY = y;
146 < *       } finally {
147 < *         if (sl.tryConvertToOptimisticRead(stamp) != 0L) // unlock or validate
148 < *           break;
149 < *       }
121 > *   double distanceFromOrigin() { // A read-only method
122 > *     long stamp = sl.tryOptimisticRead();
123 > *     double currentX = x, currentY = y;
124 > *     if (!sl.validate(stamp)) {
125 > *        stamp = sl.readLock();
126 > *        try {
127 > *          currentX = x;
128 > *          currentY = y;
129 > *        } finally {
130 > *           sl.unlockRead(stamp);
131 > *        }
132   *     }
133   *     return Math.sqrt(currentX * currentX + currentY * currentY);
134   *   }
# Line 358 | Line 340 | public class StampedLock implements java
340       * Behavior under timeout and interruption matches that specified
341       * for method {@link Lock#tryLock(long,TimeUnit)}.
342       *
343 +     * @param time the maximum time to wait for the lock
344 +     * @param unit the time unit of the {@code time} argument
345       * @return a stamp that can be used to unlock or convert mode,
346       * or zero if the lock is not available
347       * @throws InterruptedException if the current thread is interrupted
# Line 437 | Line 421 | public class StampedLock implements java
421       * Behavior under timeout and interruption matches that specified
422       * for method {@link Lock#tryLock(long,TimeUnit)}.
423       *
424 +     * @param time the maximum time to wait for the lock
425 +     * @param unit the time unit of the {@code time} argument
426       * @return a stamp that can be used to unlock or convert mode,
427       * or zero if the lock is not available
428       * @throws InterruptedException if the current thread is interrupted
# Line 502 | Line 488 | public class StampedLock implements java
488       * obtained from {@link #tryOptimisticRead} or a locking method
489       * for this lock has no defined effect or result.
490       *
491 <     * @return true if the lock has not been exclusively acquired
491 >     * @param stamp a stamp
492 >     * @return {@code true} if the lock has not been exclusively acquired
493       * since issuance of the given stamp; else false
494       */
495      public boolean validate(long stamp) {
# Line 715 | Line 702 | public class StampedLock implements java
702       * stamp value. This method may be useful for recovery after
703       * errors.
704       *
705 <     * @return true if the lock was held, else false
705 >     * @return {@code true} if the lock was held, else false
706       */
707      public boolean tryUnlockWrite() {
708          long s; WNode h;
# Line 733 | Line 720 | public class StampedLock implements java
720       * requiring a stamp value. This method may be useful for recovery
721       * after errors.
722       *
723 <     * @return true if the read lock was held, else false
723 >     * @return {@code true} if the read lock was held, else false
724       */
725      public boolean tryUnlockRead() {
726          long s, m; WNode h;
# Line 751 | Line 738 | public class StampedLock implements java
738          return false;
739      }
740  
741 +    // status monitoring methods
742 +
743      /**
744 <     * Returns true if the lock is currently held exclusively.
744 >     * Returns combined state-held and overflow read count for given
745 >     * state s.
746 >     */
747 >    private int getReadLockCount(long s) {
748 >        long readers;
749 >        if ((readers = s & RBITS) >= RFULL)
750 >            readers = RFULL + readerOverflow;
751 >        return (int) readers;
752 >    }
753 >
754 >    /**
755 >     * Returns {@code true} if the lock is currently held exclusively.
756       *
757 <     * @return true if the lock is currently held exclusively
757 >     * @return {@code true} if the lock is currently held exclusively
758       */
759      public boolean isWriteLocked() {
760          return (state & WBIT) != 0L;
761      }
762  
763      /**
764 <     * Returns true if the lock is currently held non-exclusively.
764 >     * Returns {@code true} if the lock is currently held non-exclusively.
765       *
766 <     * @return true if the lock is currently held non-exclusively
766 >     * @return {@code true} if the lock is currently held non-exclusively
767       */
768      public boolean isReadLocked() {
769          return (state & RBITS) != 0L;
770      }
771  
772 <    private void readObject(java.io.ObjectInputStream s)
773 <        throws java.io.IOException, ClassNotFoundException {
774 <        s.defaultReadObject();
775 <        state = ORIGIN; // reset to unlocked state
772 >    /**
773 >     * Queries the number of read locks held for this lock. This
774 >     * method is designed for use in monitoring system state, not for
775 >     * synchronization control.
776 >     * @return the number of read locks held
777 >     */
778 >    public int getReadLockCount() {
779 >        return getReadLockCount(state);
780 >    }
781 >
782 >    /**
783 >     * Returns a string identifying this lock, as well as its lock
784 >     * state.  The state, in brackets, includes the String {@code
785 >     * "Unlocked"} or the String {@code "Write-locked"} or the String
786 >     * {@code "Read-locks:"} followed by the current number of
787 >     * read-locks held.
788 >     *
789 >     * @return a string identifying this lock, as well as its lock state
790 >     */
791 >    public String toString() {
792 >        long s = state;
793 >        return super.toString() +
794 >            ((s & ABITS) == 0L ? "[Unlocked]" :
795 >             (s & WBIT) != 0L ? "[Write-locked]" :
796 >             "[Read-locks:" + getReadLockCount(s) + "]");
797      }
798  
799 +    // views
800 +
801      /**
802       * Returns a plain {@link Lock} view of this StampedLock in which
803       * the {@link Lock#lock} method is mapped to {@link #readLock},
# Line 889 | Line 912 | public class StampedLock implements java
912          }
913      }
914  
915 +    private void readObject(java.io.ObjectInputStream s)
916 +        throws java.io.IOException, ClassNotFoundException {
917 +        s.defaultReadObject();
918 +        state = ORIGIN; // reset to unlocked state
919 +    }
920 +
921      // internals
922  
923      /**
# Line 900 | Line 929 | public class StampedLock implements java
929       * @return new stamp on success, else zero
930       */
931      private long tryIncReaderOverflow(long s) {
932 <        // assert (s & ABITS) >= RFULL
932 >        // assert (s & ABITS) >= RFULL;
933          if ((s & ABITS) == RFULL) {
934              if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
935                  ++readerOverflow;
# Line 921 | Line 950 | public class StampedLock implements java
950       * @return new stamp on success, else zero
951       */
952      private long tryDecReaderOverflow(long s) {
953 <        // assert (s & ABITS) >= RFULL
953 >        // assert (s & ABITS) >= RFULL;
954          if ((s & ABITS) == RFULL) {
955              if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
956                  int r; long next;
# Line 1043 | Line 1072 | public class StampedLock implements java
1072                      time = 0L;
1073                  else if ((time = deadline - System.nanoTime()) <= 0L)
1074                      return cancelWaiter(node, node, false);
1075 <                node.thread = Thread.currentThread();
1075 >                Thread wt = Thread.currentThread();
1076 >                U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park
1077 >                node.thread = wt;
1078                  if (node.prev == p && p.status == WAITING && // recheck
1079                      (p != whead || (state & ABITS) != 0L))
1080                      U.park(false, time);
1081                  node.thread = null;
1082 +                U.putObject(wt, PARKBLOCKER, null);
1083                  if (interruptible && Thread.interrupted())
1084                      return cancelWaiter(node, node, true);
1085              }
# Line 1112 | Line 1144 | public class StampedLock implements java
1144                                             node.cowait = p.cowait, node)) {
1145                      node.thread = Thread.currentThread();
1146                      for (long time;;) {
1115                        if (interruptible && Thread.interrupted())
1116                            return cancelWaiter(node, p, true);
1147                          if (deadline == 0L)
1148                              time = 0L;
1149                          else if ((time = deadline - System.nanoTime()) <= 0L)
# Line 1125 | Line 1155 | public class StampedLock implements java
1155                              node.thread = null;
1156                              break;
1157                          }
1158 +                        Thread wt = Thread.currentThread();
1159 +                        U.putObject(wt, PARKBLOCKER, this);
1160                          if (node.thread == null) // must recheck
1161                              break;
1162                          U.park(false, time);
1163 +                        U.putObject(wt, PARKBLOCKER, null);
1164 +                        if (interruptible && Thread.interrupted())
1165 +                            return cancelWaiter(node, p, true);
1166                      }
1167                      group = p;
1168                  }
# Line 1183 | Line 1218 | public class StampedLock implements java
1218                      time = 0L;
1219                  else if ((time = deadline - System.nanoTime()) <= 0L)
1220                      return cancelWaiter(node, node, false);
1221 <                node.thread = Thread.currentThread();
1221 >                Thread wt = Thread.currentThread();
1222 >                U.putObject(wt, PARKBLOCKER, this);
1223 >                node.thread = wt;
1224                  if (node.prev == p && p.status == WAITING &&
1225                      (p != whead || (state & ABITS) != WBIT))
1226                      U.park(false, time);
1227                  node.thread = null;
1228 +                U.putObject(wt, PARKBLOCKER, null);
1229                  if (interruptible && Thread.interrupted())
1230                      return cancelWaiter(node, node, true);
1231              }
# Line 1288 | Line 1326 | public class StampedLock implements java
1326      private static final long WNEXT;
1327      private static final long WSTATUS;
1328      private static final long WCOWAIT;
1329 +    private static final long PARKBLOCKER;
1330  
1331      static {
1332          try {
# Line 1306 | Line 1345 | public class StampedLock implements java
1345                  (wk.getDeclaredField("next"));
1346              WCOWAIT = U.objectFieldOffset
1347                  (wk.getDeclaredField("cowait"));
1348 +            Class<?> tk = Thread.class;
1349 +            PARKBLOCKER = U.objectFieldOffset
1350 +                (tk.getDeclaredField("parkBlocker"));
1351  
1352          } catch (Exception e) {
1353              throw new Error(e);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines