1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 /*
  24  * This file is available under and governed by the GNU General Public
  25  * License version 2 only, as published by the Free Software Foundation.
  26  * However, the following notice accompanied the original version of this
  27  * file:
  28  *
  29  * Written by Doug Lea with assistance from members of JCP JSR-166
  30  * Expert Group and released to the public domain, as explained at
  31  * http://creativecommons.org/publicdomain/zero/1.0/
  32  */
  33 
  34 /*
  35  * @test
  36  * @bug 8005697
  37  * @summary Basic tests for StampedLock
  38  * @library /test/lib
  39  * @author Chris Hegarty
  40  */
  41 
  42 import static java.util.concurrent.TimeUnit.SECONDS;
  43 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  44 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  45 
  46 import java.util.Iterator;
  47 import java.util.concurrent.Phaser;
  48 import java.util.concurrent.TimeUnit;
  49 import java.util.concurrent.atomic.AtomicInteger;
  50 import java.util.concurrent.locks.Lock;
  51 import java.util.concurrent.locks.ReadWriteLock;
  52 import java.util.concurrent.locks.StampedLock;
  53 import jdk.test.lib.Utils;
  54 
  55 public class Basic {
  56     static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
  57 
  58     static void checkResult(Locker l, Class<? extends Throwable> c) {
  59         Throwable t = l.thrown();
  60         if (! ((t == null && c == null) || (c != null && c.isInstance(t)))) {
  61             fail("Mismatch in thread " +
  62                  l.getName() + ": " +
  63                  t + ", " +
  64                  (c == null ? "<null>" : c.getName()));
  65         }
  66 
  67         if (c == null)
  68             check(l.stamp() != 0L);  // must have acquired the lock
  69         else
  70             check(l.stamp() == 0L);  // must NOT have acquired the lock
  71     }
  72 
  73     //----------------------------------------------------------------
  74     // Mechanism to get all test threads into "running" mode.
  75     //----------------------------------------------------------------
  76     static void toTheStartingGate(Phaser gate) {
  77         try {
  78             gate.arriveAndAwaitAdvance();
  79         } catch (Throwable t) {
  80             unexpected(t);
  81         }
  82     }
  83 
  84     abstract static class Locker extends Thread {
  85         static AtomicInteger count = new AtomicInteger(1);
  86         private volatile Throwable thrown;
  87         private volatile long stamp;
  88         protected void thrown(Throwable thrown) { this.thrown = thrown; }
  89         public Throwable thrown() { return thrown; }
  90         protected void stamp(long stamp) { this.stamp = stamp; }
  91         public long stamp() { return stamp; }
  92 
  93         Locker() {
  94             this("Locker");
  95         }
  96 
  97         Locker(String name) {
  98             this.setName(name + ":" + count.getAndIncrement());
  99             this.setDaemon(true);
 100         }
 101     }
 102 
 103     abstract static class Reader extends Locker {
 104         Reader() { super("Reader"); }
 105         Reader(String name) { super(name); }
 106     }
 107 
 108     static Reader reader(final StampedLock sl, final Phaser gate) {
 109         return new Reader() { public void run() {
 110             if (gate != null ) toTheStartingGate(gate);
 111             stamp(sl.readLock());
 112             try {
 113                 check(sl.validate(stamp()));
 114                 check(sl.isReadLocked());
 115                 check(!sl.isWriteLocked());
 116             } finally { sl.unlockRead(stamp()); } }};
 117     }
 118 
 119     static Reader readerView(final StampedLock sl, final Phaser gate) {
 120         return new Reader("ReaderView") { public void run() {
 121             if (gate != null ) toTheStartingGate(gate);
 122             final Lock rl = sl.asReadLock();
 123             rl.lock();
 124             try {
 125                 stamp(1L);   // got the lock
 126                 check(sl.isReadLocked());
 127                 check(!sl.isWriteLocked());
 128             } finally { rl.unlock(); } }};
 129     }
 130 
 131     static Reader reader(StampedLock sl, Phaser gate, boolean view) {
 132         return view ? readerView(sl, gate) : reader(sl, gate);
 133     }
 134 
 135     static Reader interruptibleReader(final StampedLock sl,
 136                                       final long timeout,
 137                                       final TimeUnit unit,
 138                                       final Phaser gate) {
 139         return new Reader("InterruptibleReader") { public void run() {
 140             if (gate != null ) toTheStartingGate(gate);
 141             try {
 142                 if (timeout < 0)
 143                     stamp(sl.readLockInterruptibly());
 144                 else
 145                     stamp(sl.tryReadLock(timeout, unit));
 146                 check(sl.validate(stamp()));
 147                 check(sl.isReadLocked());
 148                 check(!sl.isWriteLocked());
 149             } catch (Throwable x) { thrown(x);
 150             } finally { if (stamp() != 0L) sl.unlockRead(stamp()); } }};
 151     }
 152 
 153     static Reader interruptibleReaderView(final StampedLock sl,
 154                                           final long timeout,
 155                                           final TimeUnit unit,
 156                                           final Phaser gate) {
 157         return new Reader("InterruptibleReaderView") { public void run() {
 158             if (gate != null ) toTheStartingGate(gate);
 159             final Lock rl = sl.asReadLock();
 160 
 161             try {
 162                 if (timeout < 0)
 163                     rl.lockInterruptibly();
 164                 else
 165                     rl.tryLock(timeout, unit);
 166                 stamp(1L);  // got the lock
 167                 check(sl.isReadLocked());
 168                 check(!sl.isWriteLocked());
 169             } catch (Throwable x) { thrown(x);
 170             } finally { if (stamp() != 0L) rl.unlock(); } }};
 171     }
 172 
 173     static Reader interruptibleReader(final StampedLock sl,
 174                                       final long timeout,
 175                                       final TimeUnit unit,
 176                                       final Phaser gate,
 177                                       final boolean view) {
 178         return view ? interruptibleReaderView(sl, timeout, unit, gate)
 179                     : interruptibleReader(sl, timeout, unit, gate);
 180     }
 181 
 182     abstract static class Writer extends Locker {
 183         Writer() { super("Writer"); }
 184         Writer(String name) { super(name); }
 185     }
 186 
 187     static Writer writer(final StampedLock sl, final Phaser gate) {
 188         return new Writer() { public void run() {
 189             if (gate != null ) toTheStartingGate(gate);
 190             try {
 191                 stamp(sl.writeLock());
 192                 check(sl.validate(stamp()));
 193                 check(!sl.isReadLocked());
 194                 check(sl.isWriteLocked());
 195             } finally { sl.unlockWrite(stamp()); } }};
 196     }
 197 
 198     static Writer writerView(final StampedLock sl, final Phaser gate) {
 199         return new Writer("WriterView") { public void run() {
 200             if (gate != null ) toTheStartingGate(gate);
 201             Lock wl = sl.asWriteLock();
 202             wl.lock();
 203             try {
 204                 stamp(1L);  // got the lock
 205                 check(!sl.isReadLocked());
 206                 check(sl.isWriteLocked());
 207             } finally { wl.unlock(); } }};
 208     }
 209 
 210     static Writer writer(StampedLock sl, Phaser gate, boolean view) {
 211         return view ? writerView(sl, gate) : writer(sl, gate);
 212     }
 213 
 214     static Writer interruptibleWriter(final StampedLock sl,
 215                                       final long timeout,
 216                                       final TimeUnit unit,
 217                                       final Phaser gate) {
 218         return new Writer("InterruptibleWriter") { public void run() {
 219             if (gate != null ) toTheStartingGate(gate);
 220             try {
 221                 if (timeout < 0)
 222                     stamp(sl.writeLockInterruptibly());
 223                 else
 224                     stamp(sl.tryWriteLock(timeout, unit));
 225                 check(sl.validate(stamp()));
 226                 check(!sl.isReadLocked());
 227                 check(sl.isWriteLocked());
 228             } catch (Throwable x) { thrown(x);
 229             } finally { if (stamp() != 0L) sl.unlockWrite(stamp()); } }};
 230     }
 231 
 232     static Writer interruptibleWriterView(final StampedLock sl,
 233                                           final long timeout,
 234                                           final TimeUnit unit,
 235                                           final Phaser gate) {
 236         return new Writer("InterruptibleWriterView") { public void run() {
 237             if (gate != null ) toTheStartingGate(gate);
 238             Lock wl = sl.asWriteLock();
 239             try {
 240                 if (timeout < 0)
 241                     wl.lockInterruptibly();
 242                 else
 243                     wl.tryLock(timeout, unit);
 244                 stamp(1L);  // got the lock
 245                 check(!sl.isReadLocked());
 246                 check(sl.isWriteLocked());
 247             } catch (Throwable x) { thrown(x);
 248             } finally { if (stamp() != 0L) wl.unlock(); } }};
 249     }
 250 
 251     static Writer interruptibleWriter(final StampedLock sl,
 252                                       final long timeout,
 253                                       final TimeUnit unit,
 254                                       final Phaser gate,
 255                                       final boolean view) {
 256         return view ? interruptibleWriterView(sl, timeout, unit, gate)
 257                     : interruptibleWriter(sl, timeout, unit, gate);
 258     }
 259 
 260     // Returns an infinite lazy list of all possible reader combinations.
 261     static Iterator<Reader> readerIterator(final StampedLock sl,
 262                                            final Phaser gate) {
 263         return new Iterator<Reader>() {
 264             int i = 0;
 265             boolean view = false;
 266             public boolean hasNext() { return true; }
 267             public Reader next() {
 268                 switch ((i++)&7) {
 269                     case 1: case 4: case 7:
 270                         return reader(sl, gate, view ^= true);
 271                     case 2: case 5:
 272                         return interruptibleReader(sl, -1, SECONDS, gate, view ^= true);
 273                     default:
 274                         return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
 275             public void remove() {throw new UnsupportedOperationException();}};
 276     }
 277 
 278     // Returns an infinite lazy list of all possible writer combinations.
 279     static Iterator<Writer> writerIterator(final StampedLock sl,
 280                                            final Phaser gate) {
 281         return new Iterator<Writer>() {
 282             int i = 0;
 283             boolean view = false;
 284             public boolean hasNext() { return true; }
 285             public Writer next() {
 286                 switch ((i++)&7) {
 287                     case 1: case 4: case 7:
 288                         return writer(sl, gate, view ^= true);
 289                     case 2: case 5:
 290                         return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true);
 291                     default:
 292                         return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
 293             public void remove() {throw new UnsupportedOperationException();}};
 294     }
 295 
 296     static class SimpleTimer {
 297         long startTime = System.nanoTime();
 298         long elapsedMillis() {
 299             long now = System.nanoTime();
 300             long elapsed = NANOSECONDS.toMillis(now - startTime);
 301             startTime = now;
 302             return elapsed;
 303         }
 304         void printElapsed() { System.out.println(elapsedMillis() + " ms"); }
 305     }
 306 
 307     static void waitForThreadToBlock(Thread thread) {
 308         for (long startTime = 0;;) {
 309             Thread.State state = thread.getState();
 310             if (state == Thread.State.WAITING ||
 311                 state == Thread.State.TIMED_WAITING)
 312                 break;
 313             if (startTime == 0) startTime = System.nanoTime();
 314             else if (System.nanoTime() - startTime > 10L * 1000L * 1000L * 1000L)
 315                 throw new AssertionError("timed out waiting for thread to block");
 316         }
 317     }
 318 
 319     private static void realMain(String[] args) throws Throwable {
 320         SimpleTimer timer = new SimpleTimer();
 321 
 322         //----------------------------------------------------------------
 323         System.out.print("Some basic sanity: ");
 324         //----------------------------------------------------------------
 325         try {
 326             final StampedLock sl = new StampedLock();
 327             check(!sl.isReadLocked());
 328             check(!sl.isWriteLocked());
 329             long stamp = sl.tryOptimisticRead();
 330             check(stamp != 0L);
 331             check(sl.validate(stamp));
 332             check(!sl.validate(0));
 333 
 334             stamp = sl.writeLock();
 335             try {
 336                 check(sl.validate(stamp));
 337                 check(!sl.isReadLocked());
 338                 check(sl.isWriteLocked());
 339                 check(sl.tryReadLock() == 0L);
 340                 check(sl.tryReadLock(1, MILLISECONDS) == 0L);
 341                 check(sl.tryOptimisticRead() == 0L);
 342                 check(sl.tryWriteLock() == 0L);
 343                 check(sl.tryWriteLock(1, MILLISECONDS) == 0L);
 344                 check(!sl.tryUnlockRead());
 345                 check(sl.tryConvertToWriteLock(stamp) == stamp);
 346                 try {
 347                     sl.unlockRead(stamp);
 348                     fail("Expected unlockRead to throw when not holding read lock");
 349                 } catch (IllegalMonitorStateException x) {
 350                     pass();
 351                 }
 352                 check(sl.validate(stamp));
 353             } finally {
 354                 sl.unlockWrite(stamp);
 355             }
 356             check(!sl.isWriteLocked());
 357 
 358             stamp = sl.readLock();
 359             try {
 360                 check(sl.validate(stamp));
 361                 check(sl.isReadLocked());
 362                 check(!sl.isWriteLocked());
 363                 check(sl.tryOptimisticRead() != 0L);
 364                 check(sl.tryWriteLock() == 0L);
 365                 check(sl.tryWriteLock(1, MILLISECONDS) == 0L);
 366                 check(!sl.tryUnlockWrite());
 367                 check(sl.tryConvertToReadLock(stamp) == stamp);
 368                 try {
 369                     sl.unlockWrite(stamp);
 370                     fail("Expected unlockWrite to throw when not holding read lock");
 371                 } catch (IllegalMonitorStateException x) {
 372                     pass();
 373                 }
 374                 check(sl.validate(stamp));
 375             } finally {
 376                 sl.unlockRead(stamp);
 377             }
 378             check(!sl.isReadLocked());
 379 
 380             stamp = sl.tryReadLock(1, MILLISECONDS);
 381             try {
 382                 check(stamp != 0L);
 383             } finally {
 384                 sl.unlockRead(stamp);
 385             }
 386         } catch (Throwable t) { unexpected(t); }
 387         timer.printElapsed();
 388 
 389         //----------------------------------------------------------------
 390         System.out.print("Multiple writers single reader: ");
 391         //----------------------------------------------------------------
 392         try {
 393             StampedLock sl = new StampedLock();
 394             int nThreads = 10;
 395             Phaser gate = new Phaser(nThreads + 2);
 396             Iterator<Writer> writers = writerIterator(sl, gate);
 397             Iterator<Reader> readers = readerIterator(sl, gate);
 398             for (int i = 0; i < 2; i++) {
 399                 check(!sl.isReadLocked());
 400                 check(!sl.isWriteLocked());
 401                 check(!sl.tryUnlockRead());
 402                 check(!sl.tryUnlockWrite());
 403                 check(sl.tryOptimisticRead() != 0L);
 404                 Locker[] wThreads = new Locker[nThreads];
 405                 for (int j=0; j<nThreads; j++)
 406                     wThreads[j] = writers.next();
 407                 for (int j=0; j<nThreads; j++)
 408                     wThreads[j].start();
 409                 Reader reader = readers.next(); reader.start();
 410                 toTheStartingGate(gate);
 411                 reader.join();
 412                 for (int j=0; j<nThreads; j++)
 413                     wThreads[j].join();
 414                 for (int j=0; j<nThreads; j++)
 415                     checkResult(wThreads[j], null);
 416                 checkResult(reader, null);
 417             }
 418         } catch (Throwable t) { unexpected(t); }
 419         timer.printElapsed();
 420 
 421         //----------------------------------------------------------------
 422         System.out.print("Multiple readers single writer: ");
 423         //----------------------------------------------------------------
 424         try {
 425             StampedLock sl = new StampedLock();
 426             int nThreads = 10;
 427             Phaser gate = new Phaser(nThreads + 2);
 428             Iterator<Writer> writers = writerIterator(sl, gate);
 429             Iterator<Reader> readers = readerIterator(sl, gate);
 430             for (int i = 0; i < 2; i++) {
 431                 check(!sl.isReadLocked());
 432                 check(!sl.isWriteLocked());
 433                 check(!sl.tryUnlockRead());
 434                 check(!sl.tryUnlockWrite());
 435                 check(sl.tryOptimisticRead() != 0L);
 436                 Locker[] rThreads = new Locker[nThreads];
 437                 for (int j=0; j<nThreads; j++)
 438                     rThreads[j] = readers.next();
 439                 for (int j=0; j<nThreads; j++)
 440                     rThreads[j].start();
 441                 Writer writer = writers.next(); writer.start();
 442                 toTheStartingGate(gate);
 443                 writer.join();
 444                 for (int j=0; j<nThreads; j++)
 445                     rThreads[j].join();
 446                 for (int j=0; j<nThreads; j++)
 447                     checkResult(rThreads[j], null);
 448                 checkResult(writer, null);
 449             }
 450         } catch (Throwable t) { unexpected(t); }
 451         timer.printElapsed();
 452 
 453         //----------------------------------------------------------------
 454         System.out.print("thread interrupted: ");
 455         //----------------------------------------------------------------
 456         try {
 457             // We test interrupting both before and after trying to acquire
 458             boolean view = false;
 459             StampedLock sl = new StampedLock();
 460             for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) {
 461                 long stamp;
 462                 Thread.State state;
 463 
 464                 stamp = sl.writeLock();
 465                 try {
 466                     Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
 467                     r.start();
 468                     r.interrupt();
 469                     r.join();
 470                     checkResult(r, InterruptedException.class);
 471                 } finally {
 472                     sl.unlockWrite(stamp);
 473                 }
 474 
 475                 stamp = sl.writeLock();
 476                 try {
 477                     Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
 478                     r.start();
 479                     waitForThreadToBlock(r);
 480                     r.interrupt();
 481                     r.join();
 482                     checkResult(r, InterruptedException.class);
 483                 } finally {
 484                     sl.unlockWrite(stamp);
 485                 }
 486 
 487                 stamp = sl.readLock();
 488                 try {
 489                     Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
 490                     w.start();
 491                     w.interrupt();
 492                     w.join();
 493                     checkResult(w, InterruptedException.class);
 494                 } finally {
 495                     sl.unlockRead(stamp);
 496                 }
 497 
 498                 stamp = sl.readLock();
 499                 try {
 500                     Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
 501                     w.start();
 502                     waitForThreadToBlock(w);
 503                     w.interrupt();
 504                     w.join();
 505                     checkResult(w, InterruptedException.class);
 506                 } finally {
 507                     sl.unlockRead(stamp);
 508                 }
 509 
 510                 check(!sl.isReadLocked());
 511                 check(!sl.isWriteLocked());
 512                 check(!sl.tryUnlockRead());
 513                 check(!sl.tryUnlockWrite());
 514                 check(sl.tryOptimisticRead() != 0L);
 515                 if (timeout == LONG_DELAY_MS)
 516                     view = true;
 517             }
 518         } catch (Throwable t) { unexpected(t); }
 519         timer.printElapsed();
 520 
 521         //----------------------------------------------------------------
 522         System.out.print("timeout: ");
 523         //----------------------------------------------------------------
 524         try {
 525             StampedLock sl = new StampedLock();
 526             for (long timeout : new long[] { 0L, 5L }) {
 527                 long stamp = sl.writeLock();
 528                 try {
 529                     check(sl.tryReadLock(timeout, MILLISECONDS) == 0L);
 530                 } finally {
 531                     sl.unlockWrite(stamp);
 532                 }
 533                 stamp = sl.readLock();
 534                 try {
 535                     check(sl.tryWriteLock(timeout, MILLISECONDS) == 0L);
 536                 } finally {
 537                     sl.unlockRead(stamp);
 538                 }
 539                 check(!sl.isReadLocked());
 540                 check(!sl.isWriteLocked());
 541                 check(!sl.tryUnlockRead());
 542                 check(!sl.tryUnlockWrite());
 543                 check(sl.tryOptimisticRead() != 0L);
 544             }
 545         } catch (Throwable t) { unexpected(t); }
 546         timer.printElapsed();
 547 
 548         //----------------------------------------------------------------
 549         System.out.print("optimistic read: ");
 550         //----------------------------------------------------------------
 551         try {
 552             StampedLock sl = new StampedLock();
 553             Iterator<Writer> writers = writerIterator(sl, null);
 554             Iterator<Reader> readers = readerIterator(sl, null);
 555             for (int i = 0; i < 10; i++) {
 556                 check(!sl.isReadLocked());
 557                 check(!sl.isWriteLocked());
 558                 check(!sl.tryUnlockRead());
 559                 check(!sl.tryUnlockWrite());
 560                 long stamp = sl.tryOptimisticRead();
 561                 check(stamp != 0L);
 562                 check(sl.tryConvertToOptimisticRead(stamp) == stamp);
 563                 Reader r = readers.next(); r.start();
 564                 r.join();
 565                 checkResult(r, null);
 566                 check(sl.validate(stamp));
 567                 check(sl.tryConvertToOptimisticRead(stamp) == stamp);
 568                 Writer w = writers.next(); w.start();
 569                 w.join();
 570                 checkResult(w, null);
 571                 check(sl.validate(stamp) == false);
 572             }
 573         } catch (Throwable t) { unexpected(t); }
 574         timer.printElapsed();
 575 
 576         //----------------------------------------------------------------
 577         System.out.print("convert: ");
 578         //----------------------------------------------------------------
 579         try {
 580             StampedLock sl = new StampedLock();
 581             for (int i = 0; i < 2; i++) {
 582                 check(!sl.isReadLocked());
 583                 check(!sl.isWriteLocked());
 584                 check(!sl.tryUnlockRead());
 585                 check(!sl.tryUnlockWrite());
 586                 long stamp = sl.tryOptimisticRead();
 587                 check(stamp != 0L);
 588                 check((stamp = sl.tryConvertToReadLock(stamp)) != 0L);
 589                 check(sl.validate(stamp));
 590                 check(sl.isReadLocked());
 591                 check(sl.tryWriteLock() == 0L);
 592                 check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
 593                 check((stamp = sl.tryConvertToWriteLock(stamp)) != 0L);
 594                 check(sl.validate(stamp));
 595                 check(!sl.isReadLocked());
 596                 check(sl.isWriteLocked());
 597                 check(sl.tryReadLock(1L, MILLISECONDS) == 0L);
 598                 if (i != 0) {
 599                     sl.unlockWrite(stamp);
 600                     continue;
 601                 }
 602                 // convert down
 603                 check((stamp = sl.tryConvertToReadLock(stamp)) != 0L);
 604                 check(sl.validate(stamp));
 605                 check(sl.isReadLocked());
 606                 check(!sl.isWriteLocked());
 607                 check(sl.tryWriteLock() == 0L);
 608                 check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
 609                 check((stamp = sl.tryConvertToOptimisticRead(stamp)) != 0L);
 610                 check(sl.validate(stamp));
 611                 check(!sl.isReadLocked());
 612                 check(!sl.isWriteLocked());
 613                 check(sl.validate(stamp));
 614             }
 615         } catch (Throwable t) { unexpected(t); }
 616         timer.printElapsed();
 617 
 618         //----------------------------------------------------------------
 619         System.out.print("views: ");
 620         //----------------------------------------------------------------
 621         try {
 622             StampedLock sl = new StampedLock();
 623 
 624             Lock rl = sl.asReadLock();
 625             Lock wl = sl.asWriteLock();
 626             for (int i = 0; i < 2; i++) {
 627                 rl.lock();
 628                 try {
 629                     check(sl.isReadLocked());
 630                     check(!sl.isWriteLocked());
 631                     check(sl.tryWriteLock() == 0L);
 632                     check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
 633                 } finally {
 634                     rl.unlock();
 635                 }
 636                 check(!sl.isReadLocked());
 637                 check(!sl.isWriteLocked());
 638 
 639                 wl.lock();
 640                 try {
 641                     check(!sl.isReadLocked());
 642                     check(sl.isWriteLocked());
 643                     check(sl.tryWriteLock() == 0L);
 644                     check(sl.tryWriteLock(1L, MILLISECONDS) == 0L);
 645                 } finally {
 646                     wl.unlock();
 647                 }
 648                 check(!sl.isReadLocked());
 649                 check(!sl.isWriteLocked());
 650 
 651                 ReadWriteLock rwl = sl.asReadWriteLock();
 652                 rl = rwl.readLock();
 653                 wl = rwl.writeLock();
 654             }
 655         } catch (Throwable t) { unexpected(t); }
 656         timer.printElapsed();
 657     }
 658 
 659     //--------------------- Infrastructure ---------------------------
 660     static volatile int passed = 0, failed = 0;
 661     static void pass() {passed++;}
 662     static void fail() {failed++; Thread.dumpStack();}
 663     static void fail(String msg) {System.out.println(msg); fail();}
 664     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 665     static void check(boolean cond) {if (cond) pass(); else fail();}
 666     static void equal(Object x, Object y) {
 667         if (x == null ? y == null : x.equals(y)) pass();
 668         else fail(x + " not equal to " + y);}
 669     public static void main(String[] args) throws Throwable {
 670         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 671         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 672         if (failed > 0) throw new AssertionError("Some tests failed");}
 673 }