0001: /*
0002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
0003: * notice. All rights reserved.
0004: */
0005: package com.tctest;
0006:
0007: import com.tc.exception.TCNotSupportedMethodException;
0008: import com.tc.exception.TCObjectNotSharableException;
0009: import com.tc.exception.TCRuntimeException;
0010: import com.tc.object.bytecode.ManagerUtil;
0011: import com.tc.object.config.ConfigVisitor;
0012: import com.tc.object.config.DSOClientConfigHelper;
0013: import com.tc.object.config.TransparencyClassSpec;
0014: import com.tc.object.lockmanager.api.LockLevel;
0015: import com.tc.simulator.app.ApplicationConfig;
0016: import com.tc.simulator.listener.ListenerProvider;
0017: import com.tc.util.Assert;
0018: import com.tctest.runner.AbstractTransparentApp;
0019:
0020: import java.util.LinkedList;
0021: import java.util.List;
0022: import java.util.Random;
0023: import java.util.concurrent.BrokenBarrierException;
0024: import java.util.concurrent.CyclicBarrier;
0025: import java.util.concurrent.TimeUnit;
0026: import java.util.concurrent.locks.Condition;
0027: import java.util.concurrent.locks.ReentrantLock;
0028:
0029: public class ReentrantLockTestApp extends AbstractTransparentApp {
0030: public static final String CRASH_TEST = "CRASH_TEST";
0031:
0032: private static final int NUM_OF_PUTS = 500;
0033: private static final int NUM_OF_LOOPS = 5;
0034:
0035: private final DataRoot root = new DataRoot();
0036: private final List queue = new LinkedList();
0037: private final CyclicBarrier barrier2 = new CyclicBarrier(2);
0038: private final CyclicBarrier barrier3 = new CyclicBarrier(3);
0039: private final CyclicBarrier barrier;
0040:
0041: private final Random random;
0042:
0043: private final ReentrantLock unsharedUnfairLock = new ReentrantLock();
0044: private final ReentrantLock unsharedFairLock = new ReentrantLock(
0045: true);
0046:
0047: private final Object testLockObject = new Object();
0048:
0049: private int numOfPutters = 1;
0050: private int numOfGetters;
0051: private final boolean isCrashTest;
0052:
0053: public ReentrantLockTestApp(String appId, ApplicationConfig cfg,
0054: ListenerProvider listenerProvider) {
0055: super (appId, cfg, listenerProvider);
0056: barrier = new CyclicBarrier(getParticipantCount());
0057: random = new Random(new Random(System.currentTimeMillis()
0058: + getApplicationId().hashCode()).nextLong());
0059: numOfGetters = getParticipantCount() - numOfPutters;
0060: isCrashTest = "true".equals(cfg.getAttribute(CRASH_TEST)) ? true
0061: : false;
0062: }
0063:
0064: // TODO: We need to add a test case for a situation where an unshared ReentrantLock become
0065: // shared.
0066: public void run() {
0067: try {
0068: barrier.await();
0069:
0070: sharedUnSharedTesting();
0071: multipleReentrantLocksTesting();
0072: singleNodeTryBeginLockTesting();
0073: variousLockUnLockPatternTesting();
0074:
0075: System.err.println("Testing unfair lock ...");
0076:
0077: basicConditionVariableTesting(root.getUnfairLock(), root
0078: .getUnfairCondition());
0079: basicConditionVariableWaitTesting(root.getUnfairLock(),
0080: root.getUnfairCondition());
0081: basicUnsharedLockTesting(unsharedUnfairLock);
0082: for (int i = 0; i < NUM_OF_LOOPS; i++) {
0083: basicLockTesting(root.getUnfairLock());
0084: }
0085: lockSyncLockTesting(root.getUnfairLock());
0086:
0087: tryLockTimeoutSingleNodeTesting(root.getUnfairLock());
0088: tryLockTimeoutMultiNodesTesting(root.getUnfairLock());
0089: tryLockTesting(root.getUnfairLock());
0090:
0091: threadInterruptedLockTesting(root.getUnfairLock());
0092:
0093: tryLockTest(root.getUnfairLock());
0094:
0095: System.err.println("Testing fair lock ...");
0096:
0097: basicConditionVariableTesting(root.getFairLock(), root
0098: .getFairCondition());
0099: basicConditionVariableWaitTesting(root.getFairLock(), root
0100: .getFairCondition());
0101: basicUnsharedLockTesting(unsharedFairLock);
0102: for (int i = 0; i < NUM_OF_LOOPS; i++) {
0103: basicLockTesting(root.getFairLock());
0104: }
0105: lockSyncLockTesting(root.getFairLock());
0106:
0107: tryLockTimeoutSingleNodeTesting(root.getFairLock());
0108: tryLockTimeoutMultiNodesTesting(root.getFairLock());
0109: tryLockTesting(root.getFairLock());
0110:
0111: threadInterruptedLockTesting(root.getFairLock());
0112:
0113: tryLockTest(root.getFairLock());
0114:
0115: barrier.await();
0116: } catch (Throwable t) {
0117: notifyError(t);
0118: }
0119: }
0120:
0121: private void tryLockTest(final ReentrantLock lock) throws Exception {
0122: int index = barrier.await();
0123:
0124: if (index == 0) {
0125: lock.lock();
0126: barrier2.await();
0127: barrier2.await();
0128: lock.unlock();
0129: barrier2.await();
0130: } else if (index == 1) {
0131: barrier2.await();
0132: int count = 0;
0133: for (int i = 0; i < 100; i++) {
0134: if (!lock.tryLock()) {
0135: if (lock.isLocked())
0136: count++;
0137: }
0138: }
0139: Assert.assertEquals(100, count);
0140: barrier2.await();
0141: barrier2.await();
0142: count = 0;
0143: for (int i = 0; i < 100; i++) {
0144: if (!lock.tryLock()) {
0145: if (lock.isLocked())
0146: count++;
0147: }
0148: }
0149: Assert.assertEquals(100, count);
0150: }
0151: barrier.await();
0152: }
0153:
0154: private void sharedUnSharedTesting() throws Exception {
0155: int index = barrier.await();
0156:
0157: if (index == 0) {
0158: ReentrantLock lock = new ReentrantLock();
0159: lock.lock();
0160: synchronized (root) {
0161: try {
0162: root.setLazyLock(lock);
0163: throw new AssertionError(
0164: "Should have thrown a TCObjectNotSharableException.");
0165: } catch (TCObjectNotSharableException e) {
0166: // expected
0167: }
0168: }
0169: }
0170:
0171: barrier.await();
0172:
0173: }
0174:
0175: /**
0176: * This testcase is to ensure that the unlocking sequence can be different from the locking sequence. For example,
0177: * lock1.lock(), lock2.lock(), lock1.unlock(), and lock2.unlock() as well as lock1.lock(), lock2.lock(),
0178: * lock2.unlock(), lock1.unlock() will both work correctly.
0179: */
0180: private void multipleReentrantLocksTesting() throws Exception {
0181: int index = barrier.await();
0182:
0183: if (index == 0) {
0184: root.getUnfairLock().lock();
0185: root.getFairLock().lock();
0186: }
0187:
0188: barrier.await();
0189:
0190: if (index == 0) {
0191: Assert.assertTrue(root.getUnfairLock().isLocked());
0192: Assert.assertTrue(root.getFairLock().isLocked());
0193: }
0194:
0195: barrier.await();
0196:
0197: if (index == 0) {
0198: root.getFairLock().unlock();
0199: }
0200:
0201: barrier.await();
0202:
0203: if (index == 0) {
0204: Assert.assertTrue(root.getUnfairLock().isLocked());
0205: Assert.assertFalse(root.getFairLock().isLocked());
0206: }
0207:
0208: barrier.await();
0209:
0210: if (index == 0) {
0211: root.getUnfairLock().unlock();
0212: }
0213:
0214: barrier.await();
0215:
0216: if (index == 0) {
0217: Assert.assertFalse(root.getUnfairLock().isLocked());
0218: Assert.assertFalse(root.getFairLock().isLocked());
0219: }
0220:
0221: barrier.await();
0222:
0223: if (index == 1) {
0224: root.getUnfairLock().lock();
0225: root.getFairLock().lock();
0226: }
0227:
0228: barrier.await();
0229:
0230: if (index == 1) {
0231: Assert.assertTrue(root.getUnfairLock().isLocked());
0232: Assert.assertTrue(root.getFairLock().isLocked());
0233: }
0234:
0235: barrier.await();
0236:
0237: if (index == 1) {
0238: root.getUnfairLock().unlock();
0239: }
0240:
0241: barrier.await();
0242:
0243: if (index == 1) {
0244: Assert.assertFalse(root.getUnfairLock().isLocked());
0245: Assert.assertTrue(root.getFairLock().isLocked());
0246: }
0247:
0248: barrier.await();
0249:
0250: if (index == 1) {
0251: root.getFairLock().unlock();
0252: }
0253:
0254: barrier.await();
0255:
0256: if (index == 1) {
0257: Assert.assertFalse(root.getUnfairLock().isLocked());
0258: Assert.assertFalse(root.getFairLock().isLocked());
0259: }
0260:
0261: barrier.await();
0262: }
0263:
0264: private void singleNodeTryBeginLockTesting() throws Exception {
0265: int index = barrier.await();
0266:
0267: if (index == 0) {
0268: String lockId = "testLock";
0269: CyclicBarrier localBarrier = new CyclicBarrier(2);
0270: Thread thread1 = new Thread(new TestTryLockFailRunnable(
0271: lockId, localBarrier));
0272:
0273: ManagerUtil.beginLock(lockId, LockLevel.WRITE);
0274: thread1.start();
0275: localBarrier.await();
0276: ManagerUtil.commitLock(lockId);
0277: }
0278:
0279: barrier.await();
0280: }
0281:
0282: /**
0283: * This testcase is to ensure that various lock and unlock sequence are functioned correctly. For example, lock() and
0284: * unlock() method can be invoked within a synchronized block.
0285: */
0286: private void variousLockUnLockPatternTesting() throws Exception {
0287: int index = barrier.await();
0288:
0289: if (index == 0) {
0290: root.getUnfairLock().lock();
0291: }
0292:
0293: barrier.await();
0294:
0295: if (index == 0) {
0296: Assert.assertTrue(root.getUnfairLock().isLocked());
0297: }
0298:
0299: barrier.await();
0300:
0301: if (index == 0) {
0302: synchronized (testLockObject) {
0303: root.getUnfairLock().unlock();
0304: }
0305: }
0306:
0307: barrier.await();
0308:
0309: if (index == 0) {
0310: Assert.assertFalse(root.getUnfairLock().isLocked());
0311: }
0312:
0313: barrier.await();
0314:
0315: if (index == 1) {
0316: root.getUnfairLock().lock();
0317: synchronized (testLockObject) {
0318: root.getUnfairLock().lock();
0319: }
0320: }
0321:
0322: barrier.await();
0323:
0324: if (index == 1) {
0325: Assert.assertTrue(root.getUnfairLock().isLocked());
0326: }
0327:
0328: barrier.await();
0329:
0330: if (index == 1) {
0331: root.getUnfairLock().unlock();
0332: }
0333:
0334: barrier.await();
0335:
0336: if (index == 1) {
0337: Assert.assertTrue(root.getUnfairLock().isLocked());
0338: }
0339:
0340: barrier.await();
0341:
0342: if (index == 1) {
0343: root.getUnfairLock().unlock();
0344: }
0345:
0346: barrier.await();
0347:
0348: /*
0349: * Thread thread = new Thread(new TestRunnable3(root.getUnfairLock(), testLockObject)); if (index == 0) {
0350: * thread.start(); } barrier.await(); if (index == 0) { Assert.assertTrue(root.getUnfairLock().isLocked()); }
0351: * barrier.await(); if (index == 0) { thread.interrupt(); } barrier.await();
0352: */
0353: }
0354:
0355: private void basicConditionVariableWaitTesting(ReentrantLock lock,
0356: Condition condition) throws Exception {
0357: int index = barrier.await();
0358:
0359: if (index == 0) {
0360: Thread thread = new Thread(new TestRunnable1(lock,
0361: condition));
0362: thread.start();
0363: }
0364:
0365: barrier.await();
0366:
0367: if (index == 0) {
0368: Thread.sleep(1000); // Sleep so that the TestRunnable1 thread can pick up.
0369: Assert.assertEquals(1, lock.getWaitQueueLength(condition));
0370: }
0371:
0372: barrier.await();
0373:
0374: if (index == 0) {
0375: lock.lock();
0376: try {
0377: condition.signalAll();
0378: } finally {
0379: lock.unlock();
0380: }
0381: }
0382:
0383: barrier.await();
0384:
0385: if (index == 0) {
0386: Assert.assertEquals(0, lock.getWaitQueueLength(condition));
0387: }
0388:
0389: barrier.await();
0390: }
0391:
0392: /**
0393: * This test case tests the condition variable API. A condition variable is returned by called the newCondition()
0394: * method of an reentrant lock.
0395: */
0396: private void basicConditionVariableTesting(ReentrantLock lock,
0397: Condition condition) throws Exception {
0398: int index = barrier.await();
0399:
0400: final long id = new Long(getApplicationId()).longValue();
0401:
0402: if (index == 2) {
0403: doPutter(id, lock, condition);
0404: } else {
0405: doGetter(id, lock, condition);
0406: }
0407:
0408: barrier.await();
0409: }
0410:
0411: private void doPutter(long id, ReentrantLock lock,
0412: Condition condition) throws Exception {
0413: Thread.currentThread().setName("PUTTER-" + id);
0414:
0415: for (int i = 0; i < NUM_OF_PUTS; i++) {
0416: lock.lock();
0417: try {
0418: System.err.println("PUTTER-" + id + " Putting " + i);
0419: queue.add(new WorkItem(String.valueOf(i)));
0420: if (i % 2 == 0) {
0421: condition.signalAll();
0422: } else {
0423: condition.signal();
0424: }
0425: } finally {
0426: lock.unlock();
0427: }
0428: }
0429:
0430: for (int i = 0; i < numOfGetters; i++) {
0431: lock.lock();
0432: try {
0433: queue.add(WorkItem.STOP);
0434: condition.signalAll();
0435: } finally {
0436: lock.unlock();
0437: }
0438: }
0439: }
0440:
0441: private void doGetter(long id, ReentrantLock lock,
0442: Condition condition) throws Exception {
0443: Thread.currentThread().setName("GETTER-" + id);
0444:
0445: int i = 0;
0446: while (true) {
0447: lock.lock();
0448: lock.lock();
0449: try {
0450: while (queue.size() == 0) {
0451: int choice = i % 4;
0452: switch (choice) {
0453: case 0:
0454: condition.await();
0455: break;
0456: case 1:
0457: condition.awaitUninterruptibly();
0458: break;
0459: case 2:
0460: long millis = random.nextInt(10000);
0461: condition.await(millis, TimeUnit.MILLISECONDS);
0462: break;
0463: case 3:
0464: long nanos = random.nextInt(10000);
0465: condition.awaitNanos(nanos);
0466: break;
0467: }
0468: i++;
0469: }
0470: WorkItem wi = (WorkItem) queue.remove(0);
0471: if (wi.isStop()) {
0472: return;
0473: }
0474: System.err.println("GETTER- " + id + " removes " + wi);
0475:
0476: } finally {
0477: lock.unlock();
0478: lock.unlock();
0479: }
0480: }
0481: }
0482:
0483: /**
0484: * This test case makes sure that an unshared reentrant lock is functioning as normal.
0485: */
0486: private void basicUnsharedLockTesting(ReentrantLock unsharedLock)
0487: throws Exception {
0488: int index = barrier.await();
0489:
0490: if (index == 0) {
0491: unsharedLock.lock();
0492: }
0493:
0494: barrier.await();
0495:
0496: if (index == 0) {
0497: Assert.assertTrue(unsharedLock.isLocked());
0498: } else {
0499: Assert.assertFalse(unsharedLock.isLocked());
0500: }
0501:
0502: barrier.await();
0503:
0504: if (index != 0) {
0505: boolean haveLock = unsharedLock.tryLock();
0506: Assert.assertTrue(haveLock);
0507: }
0508:
0509: barrier.await();
0510:
0511: if (index == 0) {
0512: Assert.assertTrue(unsharedLock.isLocked());
0513: } else {
0514: Assert.assertTrue(unsharedLock.isLocked());
0515: }
0516:
0517: barrier.await();
0518:
0519: if (index == 0) {
0520: unsharedLock.unlock();
0521: }
0522:
0523: barrier.await();
0524:
0525: if (index == 0) {
0526: Assert.assertFalse(unsharedLock.isLocked());
0527: } else {
0528: Assert.assertTrue(unsharedLock.isLocked());
0529: }
0530:
0531: barrier.await();
0532:
0533: if (index != 0) {
0534: unsharedLock.unlock();
0535: }
0536:
0537: barrier.await();
0538:
0539: if (index == 0) {
0540: Assert.assertFalse(unsharedLock.isLocked());
0541: } else {
0542: Assert.assertFalse(unsharedLock.isLocked());
0543: }
0544:
0545: barrier.await();
0546: }
0547:
0548: /**
0549: * This test case tests if tryLock() will throw an InterruptedException when the thread is interrupted.
0550: */
0551:
0552: private void threadInterruptedLockTesting(ReentrantLock lock)
0553: throws Exception {
0554: int index = barrier.await();
0555:
0556: if (index == 0) {
0557: lock.lock();
0558: }
0559: barrier.await();
0560: Thread thread = new Thread(new InterruptedRunnable(lock));
0561: if (index == 0) {
0562: thread.start();
0563: }
0564: barrier.await();
0565: if (index == 0) {
0566: thread.interrupt();
0567: lock.unlock();
0568: }
0569: barrier.await();
0570: }
0571:
0572: /**
0573: * This test case makes sure that data modifications within lock() and unlock() are reflected in the other client.
0574: */
0575: private void lockSyncLockTesting(ReentrantLock lock)
0576: throws Exception {
0577: int index = barrier.await();
0578:
0579: if (index == 0) {
0580: lock.lock();
0581: try {
0582: root.setData(10);
0583: } finally {
0584: lock.unlock();
0585: }
0586: }
0587:
0588: barrier.await();
0589:
0590: Assert.assertEquals(10, root.getData());
0591:
0592: barrier.await();
0593: }
0594:
0595: private void tryLockTesting(final ReentrantLock lock)
0596: throws Exception {
0597: int index = barrier.await();
0598:
0599: if (index == 1) {
0600: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0601: final CyclicBarrier threadBarrier = new CyclicBarrier(2);
0602:
0603: Thread t1 = new Thread(new Runnable() {
0604: public void run() {
0605: lock.lock();
0606: try {
0607: threadBarrier.await();
0608: threadBarrier.await();
0609: } catch (Exception e) {
0610: throw new AssertionError(e);
0611: } finally {
0612: lock.unlock();
0613: }
0614: try {
0615: localBarrier.await();
0616: } catch (Exception e) {
0617: throw new AssertionError(e);
0618: }
0619: }
0620: });
0621: Thread t2 = new Thread(new Runnable() {
0622: public void run() {
0623: try {
0624: threadBarrier.await();
0625: boolean isLocked = lock.tryLock();
0626: threadBarrier.await();
0627: Assert.assertFalse(isLocked);
0628: } catch (Exception e) {
0629: throw new AssertionError(e);
0630: }
0631: try {
0632: localBarrier.await();
0633: } catch (Exception e) {
0634: throw new AssertionError(e);
0635: }
0636: }
0637: });
0638: t1.start();
0639: t2.start();
0640: localBarrier.await();
0641: }
0642:
0643: barrier.await();
0644:
0645: if (index == 0) {
0646: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0647: final CyclicBarrier threadBarrier = new CyclicBarrier(2);
0648: final ReentrantLock nonSharedLock = new ReentrantLock();
0649:
0650: Thread t1 = new Thread(new Runnable() {
0651: public void run() {
0652: nonSharedLock.lock();
0653: try {
0654: threadBarrier.await();
0655: threadBarrier.await();
0656: } catch (Exception e) {
0657: throw new AssertionError(e);
0658: } finally {
0659: nonSharedLock.unlock();
0660: }
0661: try {
0662: localBarrier.await();
0663: } catch (Exception e) {
0664: throw new AssertionError(e);
0665: }
0666: }
0667: });
0668:
0669: Thread t2 = new Thread(new Runnable() {
0670: public void run() {
0671: try {
0672: threadBarrier.await();
0673: boolean isLocked = nonSharedLock.tryLock();
0674: threadBarrier.await();
0675: Assert.assertFalse(isLocked);
0676: } catch (Exception e) {
0677: throw new AssertionError(e);
0678: }
0679: try {
0680: localBarrier.await();
0681: } catch (Exception e) {
0682: throw new AssertionError(e);
0683: }
0684: }
0685: });
0686: t1.start();
0687: t2.start();
0688: localBarrier.await();
0689: }
0690:
0691: barrier.await();
0692:
0693: if (index == 0) {
0694: final CyclicBarrier localBarrier = new CyclicBarrier(2);
0695: final ReentrantLock nonSharedLock = new ReentrantLock();
0696:
0697: Thread t1 = new Thread(new Runnable() {
0698: public void run() {
0699: try {
0700: boolean isLocked = nonSharedLock.tryLock();
0701: Assert.assertTrue(isLocked);
0702: nonSharedLock.unlock();
0703: } catch (Exception e) {
0704: throw new AssertionError(e);
0705: }
0706: try {
0707: localBarrier.await();
0708: } catch (Exception e) {
0709: throw new AssertionError(e);
0710: }
0711: }
0712: });
0713: t1.start();
0714: localBarrier.await();
0715: }
0716:
0717: barrier.await();
0718:
0719: }
0720:
0721: private void tryLockTimeoutMultiNodesTesting(
0722: final ReentrantLock lock) throws Exception {
0723: int index = barrier.await();
0724:
0725: if (index == 0) {
0726: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0727: Thread t1 = new Thread(new Runnable() {
0728: public void run() {
0729: try {
0730: barrier3.await();
0731: lock.lock();
0732: Thread.sleep(2000);
0733: lock.unlock();
0734: } catch (Exception e) {
0735: throw new AssertionError(e);
0736: }
0737:
0738: try {
0739: localBarrier.await();
0740: } catch (Exception e) {
0741: throw new AssertionError(e);
0742: }
0743: }
0744: });
0745: Thread t2 = new Thread(new Runnable() {
0746: public void run() {
0747: try {
0748: barrier3.await();
0749: boolean isLocked = lock.tryLock(70,
0750: TimeUnit.SECONDS);
0751: assertTryLockResult(isLocked);
0752: if (isLocked) {
0753: lock.unlock();
0754: }
0755: } catch (Exception e) {
0756: throw new AssertionError(e);
0757: }
0758:
0759: try {
0760: localBarrier.await();
0761: } catch (Exception e) {
0762: throw new AssertionError(e);
0763: }
0764: }
0765: });
0766: t1.start();
0767: t2.start();
0768: localBarrier.await();
0769: barrier.await();
0770:
0771: } else if (index == 1) {
0772: lock.lock();
0773: try {
0774: barrier3.await();
0775: Thread.sleep(1000);
0776: } finally {
0777: lock.unlock();
0778: }
0779: lock.lock();
0780: try {
0781: Thread.sleep(1000);
0782: } finally {
0783: lock.unlock();
0784: }
0785: barrier.await();
0786: } else {
0787: barrier.await();
0788: }
0789:
0790: if (index == 0) {
0791: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0792: Thread t1 = new Thread(new Runnable() {
0793: public void run() {
0794: lock.lock();
0795: try {
0796: barrier2.await();
0797: Thread.sleep(1000);
0798: } catch (Exception e) {
0799: throw new AssertionError(e);
0800: } finally {
0801: lock.unlock();
0802: }
0803: try {
0804: localBarrier.await();
0805: } catch (Exception e) {
0806: throw new AssertionError(e);
0807: }
0808: }
0809: });
0810: Thread t2 = new Thread(new Runnable() {
0811: public void run() {
0812: try {
0813: boolean isLocked = lock.tryLock(9000,
0814: TimeUnit.MILLISECONDS);
0815: // boolean isLocked = lock.tryLock(9000, TimeUnit.SECONDS);
0816: assertTryLockResult(isLocked);
0817: if (isLocked) {
0818: lock.unlock();
0819: }
0820: } catch (InterruptedException e) {
0821: throw new AssertionError(e);
0822: }
0823: try {
0824: localBarrier.await();
0825: } catch (Exception e) {
0826: throw new AssertionError(e);
0827: }
0828: }
0829: });
0830: t1.start();
0831: t2.start();
0832: localBarrier.await();
0833:
0834: barrier.await();
0835: } else if (index == 1) {
0836: barrier2.await();
0837: boolean isLocked = lock
0838: .tryLock(4001, TimeUnit.MILLISECONDS);
0839: assertTryLockResult(isLocked);
0840: if (isLocked) {
0841: lock.unlock();
0842: }
0843:
0844: barrier.await();
0845: } else {
0846: barrier.await();
0847: }
0848:
0849: if (index == 0) {
0850: lock.lock();
0851: try {
0852: Thread.sleep(1000);
0853: } finally {
0854: lock.unlock();
0855: }
0856: barrier.await();
0857: } else if (index == 1) {
0858: boolean isLocked = lock
0859: .tryLock(4000, TimeUnit.MILLISECONDS);
0860: assertTryLockResult(isLocked);
0861: if (isLocked) {
0862: lock.unlock();
0863: }
0864:
0865: barrier.await();
0866: } else {
0867: barrier.await();
0868: }
0869:
0870: if (index == 0) {
0871: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0872: Thread t1 = new Thread(new Runnable() {
0873: public void run() {
0874: lock.lock();
0875: try {
0876: Thread.sleep(1000);
0877: } catch (InterruptedException e) {
0878: throw new AssertionError(e);
0879: } finally {
0880: lock.unlock();
0881: }
0882: try {
0883: localBarrier.await();
0884: } catch (Exception e) {
0885: throw new AssertionError(e);
0886: }
0887: }
0888: });
0889: Thread t2 = new Thread(new Runnable() {
0890: public void run() {
0891: try {
0892: boolean isLocked = lock.tryLock(9001,
0893: TimeUnit.MILLISECONDS);
0894: // boolean isLocked = lock.tryLock(60, TimeUnit.SECONDS);
0895: assertTryLockResult(isLocked);
0896: if (isLocked) {
0897: lock.unlock();
0898: }
0899: } catch (InterruptedException e) {
0900: throw new AssertionError(e);
0901: }
0902: try {
0903: localBarrier.await();
0904: } catch (Exception e) {
0905: throw new AssertionError(e);
0906: }
0907: }
0908: });
0909: t1.start();
0910: t2.start();
0911: localBarrier.await();
0912:
0913: barrier.await();
0914: } else if (index == 1) {
0915: boolean isLocked = lock
0916: .tryLock(4001, TimeUnit.MILLISECONDS);
0917: assertTryLockResult(isLocked);
0918: if (isLocked) {
0919: lock.unlock();
0920: }
0921:
0922: barrier.await();
0923: } else {
0924: barrier.await();
0925: }
0926:
0927: }
0928:
0929: private void tryLockTimeoutSingleNodeTesting(
0930: final ReentrantLock lock) throws Exception {
0931: int index = barrier.await();
0932:
0933: if (index == 1) {
0934: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0935: Thread t1 = new Thread(new Runnable() {
0936: public void run() {
0937: lock.lock();
0938: try {
0939: Thread.sleep(1000);
0940: } catch (InterruptedException e) {
0941: throw new AssertionError(e);
0942: } finally {
0943: lock.unlock();
0944: }
0945: try {
0946: localBarrier.await();
0947: } catch (Exception e) {
0948: throw new AssertionError(e);
0949: }
0950: }
0951: });
0952: Thread t2 = new Thread(new Runnable() {
0953: public void run() {
0954: try {
0955: boolean isLocked = lock.tryLock(4002,
0956: TimeUnit.MILLISECONDS);
0957: // boolean isLocked = lock.tryLock(60, TimeUnit.SECONDS);
0958: assertTryLockResult(isLocked);
0959: if (isLocked) {
0960: lock.unlock();
0961: }
0962: } catch (InterruptedException e) {
0963: throw new AssertionError(e);
0964: }
0965: try {
0966: localBarrier.await();
0967: } catch (Exception e) {
0968: throw new AssertionError(e);
0969: }
0970: }
0971: });
0972: t1.start();
0973: t2.start();
0974: localBarrier.await();
0975: }
0976:
0977: barrier.await();
0978:
0979: if (index == 0) {
0980: final CyclicBarrier localBarrier = new CyclicBarrier(3);
0981: final ReentrantLock nonSharedLock = new ReentrantLock();
0982:
0983: Thread t1 = new Thread(new Runnable() {
0984: public void run() {
0985: nonSharedLock.lock();
0986: try {
0987: Thread.sleep(1000);
0988: } catch (InterruptedException e) {
0989: throw new AssertionError(e);
0990: } finally {
0991: nonSharedLock.unlock();
0992: }
0993: try {
0994: localBarrier.await();
0995: } catch (Exception e) {
0996: throw new AssertionError(e);
0997: }
0998: }
0999: });
1000:
1001: Thread t2 = new Thread(new Runnable() {
1002: public void run() {
1003: try {
1004: boolean isLocked = nonSharedLock.tryLock(5,
1005: TimeUnit.SECONDS);
1006: assertTryLockResult(isLocked);
1007: if (isLocked) {
1008: nonSharedLock.unlock();
1009: }
1010: } catch (InterruptedException e) {
1011: throw new AssertionError(e);
1012: }
1013: try {
1014: localBarrier.await();
1015: } catch (Exception e) {
1016: throw new AssertionError(e);
1017: }
1018: }
1019: });
1020: t1.start();
1021: t2.start();
1022: localBarrier.await();
1023: }
1024:
1025: barrier.await();
1026:
1027: if (index == 0) {
1028: final CyclicBarrier localBarrier = new CyclicBarrier(3);
1029: final ReentrantLock nonSharedLock = new ReentrantLock();
1030:
1031: Thread t1 = new Thread(new Runnable() {
1032: public void run() {
1033: nonSharedLock.lock();
1034: try {
1035: Thread.sleep(1000);
1036: } catch (InterruptedException e) {
1037: throw new AssertionError(e);
1038: } finally {
1039: nonSharedLock.unlock();
1040: }
1041: try {
1042: localBarrier.await();
1043: } catch (Exception e) {
1044: throw new AssertionError(e);
1045: }
1046: }
1047: });
1048:
1049: Thread t2 = new Thread(new Runnable() {
1050: public void run() {
1051: try {
1052: boolean isLocked = nonSharedLock.tryLock(
1053: TimeUnit.MICROSECONDS.convert(6,
1054: TimeUnit.SECONDS),
1055: TimeUnit.MICROSECONDS);
1056: assertTryLockResult(isLocked);
1057: if (isLocked) {
1058: nonSharedLock.unlock();
1059: }
1060: } catch (InterruptedException e) {
1061: throw new AssertionError(e);
1062: }
1063: try {
1064: localBarrier.await();
1065: } catch (Exception e) {
1066: throw new AssertionError(e);
1067: }
1068: }
1069: });
1070: t1.start();
1071: t2.start();
1072: localBarrier.await();
1073: }
1074:
1075: barrier.await();
1076:
1077: if (index == 0) {
1078: final CyclicBarrier localBarrier = new CyclicBarrier(3);
1079: final CyclicBarrier threadBarrier = new CyclicBarrier(2);
1080: final ReentrantLock nonSharedLock = new ReentrantLock();
1081:
1082: Thread t1 = new Thread(new Runnable() {
1083: public void run() {
1084: nonSharedLock.lock();
1085: try {
1086: threadBarrier.await();
1087: threadBarrier.await();
1088: } catch (Exception e) {
1089: throw new AssertionError(e);
1090: } finally {
1091: nonSharedLock.unlock();
1092: }
1093: try {
1094: localBarrier.await();
1095: } catch (Exception e) {
1096: throw new AssertionError(e);
1097: }
1098: }
1099: });
1100:
1101: Thread t2 = new Thread(new Runnable() {
1102: public void run() {
1103: try {
1104: threadBarrier.await();
1105: boolean isLocked = nonSharedLock.tryLock(10,
1106: TimeUnit.MICROSECONDS);
1107: threadBarrier.await();
1108: assertTryLockResult(!isLocked);
1109: } catch (Exception e) {
1110: throw new AssertionError(e);
1111: }
1112: try {
1113: localBarrier.await();
1114: } catch (Exception e) {
1115: throw new AssertionError(e);
1116: }
1117: }
1118: });
1119: t1.start();
1120: t2.start();
1121: localBarrier.await();
1122: }
1123:
1124: barrier.await();
1125: }
1126:
1127: /**
1128: * This test case provides basic testing to the API of an reentrant lock when an reentrant lock is shared.
1129: */
1130: private void basicLockTesting(ReentrantLock lock) throws Exception {
1131: int index = barrier.await();
1132:
1133: if (index == 0) {
1134: lock.lock();
1135: boolean isLocked = lock.tryLock();
1136:
1137: Assert.assertTrue(isLocked);
1138:
1139: isLocked = lock.tryLock(300000L, TimeUnit.NANOSECONDS);
1140:
1141: Assert.assertTrue(isLocked);
1142:
1143: lock.unlock();
1144:
1145: try {
1146: lock.hasQueuedThread(Thread.currentThread());
1147: throw new AssertionError(
1148: "Should have thrown an TCNotSupportedMethodException.");
1149: } catch (TCNotSupportedMethodException e) {
1150: // Expected
1151: }
1152: }
1153: barrier.await();
1154:
1155: if (index != 0) {
1156: boolean haveLocked = lock.tryLock();
1157: Assert.assertFalse(haveLocked);
1158:
1159: haveLocked = lock.tryLock(300000L, TimeUnit.NANOSECONDS);
1160: Assert.assertFalse(haveLocked);
1161: }
1162:
1163: barrier.await();
1164:
1165: if (index == 0) {
1166: Assert.assertEquals(2, lock.getHoldCount());
1167: } else {
1168: Assert.assertEquals(0, lock.getHoldCount());
1169: }
1170:
1171: Assert.assertEquals(0, lock.getQueueLength());
1172:
1173: Assert.assertFalse(lock.hasQueuedThreads());
1174:
1175: if (index == 0) {
1176: Assert.assertTrue(lock.isHeldByCurrentThread());
1177: } else {
1178: Assert.assertFalse(lock.isHeldByCurrentThread());
1179: }
1180: Assert.assertTrue(lock.isLocked());
1181:
1182: barrier.await();
1183:
1184: if (index == 0) {
1185: lock.unlock();
1186: }
1187:
1188: barrier.await();
1189:
1190: Assert.assertTrue(lock.isLocked());
1191:
1192: barrier.await();
1193:
1194: if (index == 0) {
1195: lock.unlock();
1196: }
1197:
1198: barrier.await();
1199:
1200: Assert.assertEquals(0, lock.getQueueLength());
1201: Assert.assertFalse(lock.isLocked());
1202:
1203: barrier.await();
1204: }
1205:
1206: private void assertTryLockResult(boolean isLocked) {
1207: if (!isCrashTest) {
1208: Assert.assertTrue(isLocked);
1209: }
1210: }
1211:
1212: public static void visitL1DSOConfig(ConfigVisitor visitor,
1213: DSOClientConfigHelper config) {
1214: String testClass = ReentrantLockTestApp.class.getName();
1215: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
1216:
1217: config.addIncludePattern(testClass + "$*");
1218:
1219: String methodExpression = "* " + testClass + "*.*(..)";
1220: config.addWriteAutolock(methodExpression);
1221:
1222: spec.addRoot("root", "root");
1223: spec.addRoot("barrier", "barrier");
1224: spec.addRoot("barrier2", "barrier2");
1225: spec.addRoot("barrier3", "barrier3");
1226: spec.addRoot("queue", "queue");
1227: spec.addRoot("testLockObject", "testLockObject");
1228: }
1229:
1230: private static class TestRunnable1 implements Runnable {
1231: private ReentrantLock lock;
1232: private Condition conditionObject;
1233:
1234: public TestRunnable1(ReentrantLock lock,
1235: Condition conditionObject) {
1236: this .lock = lock;
1237: this .conditionObject = conditionObject;
1238: }
1239:
1240: public void run() {
1241: lock.lock();
1242: try {
1243: conditionObject.await();
1244: } catch (InterruptedException e) {
1245: throw new TCRuntimeException(e);
1246: } finally {
1247: lock.unlock();
1248: }
1249: }
1250: }
1251:
1252: private class TestRunnable2 implements Runnable {
1253: private ReentrantLock lock;
1254:
1255: public TestRunnable2(ReentrantLock lock) {
1256: this .lock = lock;
1257: }
1258:
1259: public void run() {
1260: lock.lock();
1261: try {
1262: Thread.sleep(10000);
1263: } catch (InterruptedException e) {
1264: throw new TCRuntimeException(e);
1265: } finally {
1266: lock.unlock();
1267: try {
1268: barrier2.await();
1269: } catch (InterruptedException e) {
1270: throw new TCRuntimeException(e);
1271: } catch (BrokenBarrierException e) {
1272: throw new TCRuntimeException(e);
1273: }
1274: }
1275: }
1276: }
1277:
1278: private class InterruptedRunnable implements Runnable {
1279: private ReentrantLock lock;
1280:
1281: public InterruptedRunnable(ReentrantLock lock) {
1282: this .lock = lock;
1283: }
1284:
1285: public void run() {
1286: try {
1287: try {
1288: lock.lock();
1289: System.err.println(Thread.currentThread()
1290: .interrupted());
1291: } catch (TCRuntimeException e) {
1292: Assert
1293: .assertFalse(isCausedByInterruptedException(e));
1294: }
1295: } finally {
1296: lock.unlock();
1297: }
1298:
1299: }
1300: }
1301:
1302: private boolean isCausedByInterruptedException(TCRuntimeException e) {
1303: if (e.getCause() instanceof InterruptedException) {
1304: return true;
1305: } else {
1306: return false;
1307: }
1308: }
1309:
1310: private class TestTryLockFailRunnable implements Runnable {
1311: private String lockId;
1312: private CyclicBarrier barrier;
1313:
1314: public TestTryLockFailRunnable(String lockId,
1315: CyclicBarrier barrier) {
1316: this .lockId = lockId;
1317: this .barrier = barrier;
1318: }
1319:
1320: public void run() {
1321: try {
1322: boolean locked = ManagerUtil.tryBeginLock(lockId,
1323: LockLevel.WRITE);
1324:
1325: Assert.assertFalse(locked);
1326: this .barrier.await();
1327: } catch (Exception e) {
1328: throw new TCRuntimeException(e);
1329: }
1330: }
1331: }
1332:
1333: /*
1334: * private static class TestRunnable3 implements Runnable { private ReentrantLock lock; private Object sharedObject;
1335: * public TestRunnable3(ReentrantLock lock, Object obj) { this.lock = lock; this.sharedObject = obj; } public void
1336: * run() { synchronized(sharedObject) { try { lock.lock(); sharedObject.wait(); } catch (InterruptedException e) {
1337: * lock.unlock(); } finally { lock.unlock(); } } } }
1338: */
1339:
1340: private static class DataRoot {
1341: private ReentrantLock unfairLock = new ReentrantLock();
1342:
1343: // When an reentrant lock is shared,
1344: // the fairness is current not supported.
1345: private ReentrantLock fairLock = new ReentrantLock(true);
1346: private Condition unfairCondition = unfairLock.newCondition();
1347: private Condition fairCondition = fairLock.newCondition();
1348: private ReentrantLock lazyLock;
1349: private int data;
1350:
1351: public DataRoot() {
1352: super ();
1353: }
1354:
1355: public ReentrantLock getFairLock() {
1356: return fairLock;
1357: }
1358:
1359: public void setFairLock(ReentrantLock fairLock) {
1360: this .fairLock = fairLock;
1361: }
1362:
1363: public ReentrantLock getUnfairLock() {
1364: return unfairLock;
1365: }
1366:
1367: public void setUnfairLock(ReentrantLock unfairLock) {
1368: this .unfairLock = unfairLock;
1369: }
1370:
1371: public int getData() {
1372: return data;
1373: }
1374:
1375: public void setData(int data) {
1376: this .data = data;
1377: }
1378:
1379: public ReentrantLock getLazyLock() {
1380: return lazyLock;
1381: }
1382:
1383: public void setLazyLock(ReentrantLock lazyLock) {
1384: this .lazyLock = lazyLock;
1385: }
1386:
1387: public Condition getUnfairCondition() {
1388: return unfairCondition;
1389: }
1390:
1391: public void setUnfairCondition(Condition unfairCondition) {
1392: this .unfairCondition = unfairCondition;
1393: }
1394:
1395: public Condition getFairCondition() {
1396: return fairCondition;
1397: }
1398:
1399: public void setFairCondition(Condition fairCondition) {
1400: this .fairCondition = fairCondition;
1401: }
1402:
1403: public void clear() {
1404: this .data = 0;
1405: }
1406: }
1407:
1408: private static class WorkItem {
1409: static final WorkItem STOP = new WorkItem("STOP");
1410:
1411: private final String name;
1412:
1413: WorkItem(String name) {
1414: this .name = name;
1415: }
1416:
1417: boolean isStop() {
1418: return STOP.name.equals(name);
1419: }
1420:
1421: public String toString() {
1422: return this.name;
1423: }
1424: }
1425: }
|