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.1 by dl, Fri Oct 12 14:09:30 2012 UTC vs.
Revision 1.7 by dl, Fri Oct 12 23:11:14 2012 UTC

# Line 26 | Line 26 | import java.util.concurrent.TimeUnit;
26   *   in method {@link #unlockWrite} to release the lock. Untimed and
27   *   timed versions of {@code tryWriteLock} are also provided. When
28   *   the lock is held in write mode, no read locks may be obtained,
29 < *   and all observer validations will fail.  </li>
29 > *   and all optimistic read validations will fail.  </li>
30   *
31   *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
32   *   waiting for non-exclusive access, returning a stamp that can be
# Line 76 | Line 76 | import java.util.concurrent.TimeUnit;
76   * into initial unlocked state, so they are not useful for remote
77   * locking.
78   *
79 < * <p>The scheduling policy of StampedLock does not consistently prefer
80 < * readers over writers or vice versa.
79 > * <p>The scheduling policy of StampedLock does not consistently
80 > * prefer readers over writers or vice versa.  A zero return from any
81 > * "try" method for acquiring or converting locks does carry any
82 > * information about the state of the lock; a subsequent invocation
83 > * may succeed.
84   *
85   * <p><b>Sample Usage.</b> The following illustrates some usage idioms
86   * in a class that maintains simple two-dimensional points. The sample
# Line 87 | Line 90 | import java.util.concurrent.TimeUnit;
90   *
91   *  <pre>{@code
92   * class Point {
93 < *   private volatile double x, y;
93 > *   private double x, y;
94   *   private final StampedLock sl = new StampedLock();
95   *
96   *   void move(double deltaX, double deltaY) { // an exclusively locked method
# Line 119 | Line 122 | import java.util.concurrent.TimeUnit;
122   *   }
123   *
124   *   double distanceFromOriginV2() { // combines code paths
125 < *     for (long stamp = sl.optimisticRead(); ; stamp = sl.readLock()) {
125 > *     for (long stamp = sl.tryOptimisticRead(); ; stamp = sl.readLock()) {
126   *       double currentX, currentY;
127   *       try {
128   *         currentX = x;
# Line 177 | Line 180 | public class StampedLock implements java
180       * read-locked.  The read count is ignored when validating
181       * "optimistic" seqlock-reader-style stamps.  Because we must use
182       * a small finite number of bits (currently 7) for readers, a
183 <     * supplementatry reader overflow word is used when then number of
183 >     * supplementary reader overflow word is used when then number of
184       * readers exceeds the count field. We do this by treating the max
185       * reader count value (RBITS) as a spinlock protecting overflow
186       * updates.
# Line 235 | Line 238 | public class StampedLock implements java
238      private static final int NCPU = Runtime.getRuntime().availableProcessors();
239  
240      /** Maximum number of retries before blocking on acquisition */
241 <    private static final int SPINS = NCPU > 1 ? 1 << 6 : 1;
241 >    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
242  
243 <    /** Maximum number of retries before re-blocking on write lock */
244 <    private static final int MAX_HEAD_SPINS = NCPU > 1 ? 1 << 12 : 1;
243 >    /** Maximum number of retries before re-blocking */
244 >    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 1;
245  
246      /** The period for yielding when waiting for overflow spinlock */
247      private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
# Line 303 | Line 306 | public class StampedLock implements java
306       * Exclusively acquires the lock, blocking if necessary
307       * until available.
308       *
309 <     * @return a stamp that can be used to unlock or convert mode.
309 >     * @return a stamp that can be used to unlock or convert mode
310       */
311      public long writeLock() {
312          long s, next;
# Line 329 | Line 332 | public class StampedLock implements java
332  
333      /**
334       * Exclusively acquires the lock if it is available within the
335 <     * given time and the current thread has not been interrupted
335 >     * given time and the current thread has not been interrupted.
336       *
337       * @return a stamp that can be used to unlock or convert mode,
338 <     * or zero if the lock is not available.
338 >     * or zero if the lock is not available
339       * @throws InterruptedException if the current thread is interrupted
340 <     * before acquiring the lock.
340 >     * before acquiring the lock
341       */
342      public long tryWriteLock(long time, TimeUnit unit)
343          throws InterruptedException {
344 <        long nanos =  unit.toNanos(time);
344 >        long nanos = unit.toNanos(time);
345          if (!Thread.interrupted()) {
346              long s, next, deadline;
347              if (((s = state) & ABITS) == 0L &&
# Line 358 | Line 361 | public class StampedLock implements java
361       * Exclusively acquires the lock, blocking if necessary
362       * until available or the current thread is interrupted.
363       *
364 <     * @return a stamp that can be used to unlock or convert mode.
364 >     * @return a stamp that can be used to unlock or convert mode
365       * @throws InterruptedException if the current thread is interrupted
366 <     * before acquiring the lock.
366 >     * before acquiring the lock
367       */
368      public long writeLockInterruptibly() throws InterruptedException {
369          if (!Thread.interrupted()) {
# Line 378 | Line 381 | public class StampedLock implements java
381       * Non-exclusively acquires the lock, blocking if necessary
382       * until available.
383       *
384 <     * @return a stamp that can be used to unlock or convert mode.
384 >     * @return a stamp that can be used to unlock or convert mode
385       */
386      public long readLock() {
387          for (;;) {
# Line 401 | Line 404 | public class StampedLock implements java
404       * Non-exclusively acquires the lock if it is immediately available.
405       *
406       * @return a stamp that can be used to unlock or convert mode,
407 <     * or zero if the lock is not available.
407 >     * or zero if the lock is not available
408       */
409      public long tryReadLock() {
410          for (;;) {
# Line 419 | Line 422 | public class StampedLock implements java
422  
423      /**
424       * Non-exclusively acquires the lock if it is available within the
425 <     * given time and the current thread has not been interrupted
425 >     * given time and the current thread has not been interrupted.
426       *
427       * @return a stamp that can be used to unlock or convert mode,
428 <     * or zero if the lock is not available.
428 >     * or zero if the lock is not available
429       * @throws InterruptedException if the current thread is interrupted
430 <     * before acquiring the lock.
430 >     * before acquiring the lock
431       */
432      public long tryReadLock(long time, TimeUnit unit)
433          throws InterruptedException {
# Line 457 | Line 460 | public class StampedLock implements java
460       * Non-exclusively acquires the lock, blocking if necessary
461       * until available or the current thread is interrupted.
462       *
463 <     * @return a stamp that can be used to unlock or convert mode.
463 >     * @return a stamp that can be used to unlock or convert mode
464       * @throws InterruptedException if the current thread is interrupted
465 <     * before acquiring the lock.
465 >     * before acquiring the lock
466       */
467      public long readLockInterruptibly() throws InterruptedException {
468          if (!Thread.interrupted()) {
# Line 512 | Line 515 | public class StampedLock implements java
515       *
516       * @param stamp a stamp returned by a write-lock operation
517       * @throws IllegalMonitorStateException if the stamp does
518 <     * not match the current state of this lock.
518 >     * not match the current state of this lock
519       */
520      public void unlockWrite(long stamp) {
521          if (state != stamp || (stamp & WBIT) == 0L)
# Line 527 | Line 530 | public class StampedLock implements java
530       *
531       * @param stamp a stamp returned by a read-lock operation
532       * @throws IllegalMonitorStateException if the stamp does
533 <     * not match the current state of this lock.
533 >     * not match the current state of this lock
534       */
535      public void unlockRead(long stamp) {
536          long s, m;
# Line 557 | Line 560 | public class StampedLock implements java
560       *
561       * @param stamp a stamp returned by a lock operation
562       * @throws IllegalMonitorStateException if the stamp does
563 <     * not match the current state of this lock.
563 >     * not match the current state of this lock
564       */
565      public void unlock(long stamp) {
566          long a = stamp & ABITS, m, s;
# Line 673 | Line 676 | public class StampedLock implements java
676       */
677      public long tryConvertToOptimisticRead(long stamp) {
678          long a = stamp & ABITS, m, s, next;
679 <        while (((s = U.getLongVolatile(this, STATE)) &
679 >        while (((s = U.getLongVolatile(this, STATE)) &
680                  SBITS) == (stamp & SBITS)) {
681              if ((m = s & ABITS) == 0L) {
682                  if (a != 0L)
# Line 707 | Line 710 | public class StampedLock implements java
710       * stamp value. This method may be useful for recovery after
711       * errors.
712       *
713 <     * @return true if the lock was held, else false.
713 >     * @return true if the lock was held, else false
714       */
715      public boolean tryUnlockWrite() {
716          long s;
# Line 724 | Line 727 | public class StampedLock implements java
727       * requiring a stamp value. This method may be useful for recovery
728       * after errors.
729       *
730 <     * @return true if the read lock was held, else false.
730 >     * @return true if the read lock was held, else false
731       */
732      public boolean tryUnlockRead() {
733          long s, m;
# Line 773 | Line 776 | public class StampedLock implements java
776       * Tries to increment readerOverflow by first setting state
777       * access bits value to RBITS, indicating hold of spinlock,
778       * then updating, then releasing.
779 +     *
780       * @param stamp, assumed that (stamp & ABITS) >= RFULL
781       * @return new stamp on success, else zero
782       */
# Line 784 | Line 788 | public class StampedLock implements java
788                  return s;
789              }
790          }
791 <        else if ((ThreadLocalRandom.current().nextInt() &
791 >        else if ((ThreadLocalRandom.current().nextInt() &
792                    OVERFLOW_YIELD_RATE) == 0)
793              Thread.yield();
794          return 0L;
# Line 792 | Line 796 | public class StampedLock implements java
796  
797      /**
798       * Tries to decrement readerOverflow.
799 +     *
800       * @param stamp, assumed that (stamp & ABITS) >= RFULL
801       * @return new stamp on success, else zero
802       */
# Line 809 | Line 814 | public class StampedLock implements java
814                   return next;
815              }
816          }
817 <        else if ((ThreadLocalRandom.current().nextInt() &
817 >        else if ((ThreadLocalRandom.current().nextInt() &
818                    OVERFLOW_YIELD_RATE) == 0)
819              Thread.yield();
820          return 0L;
# Line 911 | Line 916 | public class StampedLock implements java
916  
917      /**
918       * Possibly spins trying to obtain write lock, then enqueues and
919 <     * blocks while not head of write queue or cannot aquire lock,
919 >     * blocks while not head of write queue or cannot acquire lock,
920       * possibly spinning when at head; cancelling on timeout or
921       * interrupt.
922       *
923       * @param interruptible true if should check interrupts and if so
924       * return INTERRUPTED
925       * @param deadline if nonzero, the System.nanoTime value to timeout
926 <     * at (and return zero).
926 >     * at (and return zero)
927       */
928      private long awaitWrite(boolean interruptible, long deadline) {
929          WNode node = null;
# Line 1019 | Line 1024 | public class StampedLock implements java
1024              }
1025          }
1026          writerPrefSignal();
1027 <        return (interrupted || Thread.interrupted())? INTERRUPTED : 0L;
1027 >        return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1028      }
1029  
1030 <    /*
1030 >    /**
1031       * Waits for read lock or timeout or interrupt. The form of
1032       * awaitRead differs from awaitWrite mainly because it must
1033       * restart (with a new wait node) if the thread was unqueued and
# Line 1101 | Line 1106 | public class StampedLock implements java
1106      /**
1107       * If node non-null, forces cancel status and unsplices from queue
1108       * if possible, by traversing entire queue looking for cancelled
1109 <     * nodes, cleaning out all at head, but stopping upon first
1105 <     * encounter otherwise.
1109 >     * nodes.
1110       */
1111      private long cancelReader(RNode node, boolean interrupted) {
1112          Thread w;
# Line 1117 | Line 1121 | public class StampedLock implements java
1121                      }
1122                      else {
1123                          U.compareAndSwapObject(pred, RNEXT, p, q);
1124 <                        break;
1124 >                        p = pred.next;
1125                      }
1126                  }
1127                  else {
# Line 1127 | Line 1131 | public class StampedLock implements java
1131              }
1132          }
1133          readerPrefSignal();
1134 <        return (interrupted || Thread.interrupted())? INTERRUPTED : 0L;
1134 >        return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1135      }
1136  
1137      // Unsafe mechanics
# Line 1201 | Line 1205 | public class StampedLock implements java
1205      }
1206  
1207   }
1204

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines