[jbosscache-commits] JBoss Cache SVN: r7505 - core/trunk/src/test/java/org/jboss/cache/lock.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Mon Jan 19 04:42:32 EST 2009


Author: mircea.markus
Date: 2009-01-19 04:42:32 -0500 (Mon, 19 Jan 2009)
New Revision: 7505

Modified:
   core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java
Log:
more strict threading control

Modified: core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java	2009-01-18 19:36:17 UTC (rev 7504)
+++ core/trunk/src/test/java/org/jboss/cache/lock/ReadWriteLockWithUpgradeTest.java	2009-01-19 09:42:32 UTC (rev 7505)
@@ -8,6 +8,7 @@
 
 import java.util.Vector;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.locks.Lock;
 
 /**
@@ -82,183 +83,214 @@
     * <p/>
     * Each test case should also call cleanLockingResult() to reset
     * result vector for the next test cases.
-    *
-    * @param caseNum  Arbitrary string for the test case number.
-    * @param name     Arbitrary string for the calling thread name.
-    * @param msecs    Milliseconds that the thread should sleep after
-    *                 acquiring the read lock.
-    * @param errMsg   Error msg to log in case of error.
-    * @param secondOP Set to NO_MORE_OP if a 2nd lock request is not required.
-    *                 Set to INVOKE_READ, INVOKE_READ or INVOKE_UPGRADE
-    *                 respectively if the 2nd lock is a read, write or
-    *                 upgrade request respectively.
     */
 
-   protected Thread readThread(final String caseNum, final String name,
-                               final long msecs, final long sleepSecs,
-                               final String errMsg, final int secondOP)
+   class ReadThread extends Thread
    {
-      return new Thread(name)
-      {
-         public void run()
-         {
-            Lock rlock = lock_.readLock();
-            try
-            {
-               if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
-               {
-                  String str = caseNum + "-" + name + "-RL-0";
-                  postLockingResult(str);
-                  return;
-               }
-               // OK, read lock obtained, sleep and release it.
-               String str = caseNum + "-" + name + "-RL-1";
-               postLockingResult(str);
-               TestingUtil.sleepThread(sleepSecs);
 
-               if (secondOP == INVOKE_READ)
-               {
-                  acquireReadLock(caseNum, name, msecs, errMsg);
-               }
-               else if (secondOP == INVOKE_WRITE)
-               {
-                  acquireWriteLock(caseNum, name, msecs, errMsg);
-               }
-               else if (secondOP == INVOKE_UPGRADE)
-               {
-                  acquireUpgradeLock(caseNum, name, msecs, errMsg);
-               }
+     private String caseNum;
+     private String name;
+     volatile CountDownLatch notifyBeforeSecondOp = new CountDownLatch(1);
+     volatile CountDownLatch notifyBeforeFinish = new CountDownLatch(1);
+     volatile CountDownLatch waitLatch;
+     private String errMsg;
+     private int secondOP;
 
-               rlock.unlock();
-            }
-            catch (Exception ex)
-            {
-            }
-         }
-      };
-   }
+     ReadThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch waitLatch) {
+       this.caseNum = caseNum;
+       this.name = name;
+       this.errMsg = errMsg;
+       this.secondOP = secondOP;
+       this.waitLatch = waitLatch;
+     }
 
-   /**
-    * Creates a new thread and acquires a write lock with a timeout
-    * value specified by the caller. Similar to {@link #readThread readThread()}
-    * except it's used for write locks.
-    *
-    * @see #readThread readThread()
-    */
-   protected Thread writeThread(final String caseNum, final String name,
-                                final long msecs, final long sleepSecs,
-                                final String errMsg, final int secondOP)
-   {
-      return new Thread(name)
-      {
-         public void run()
-         {
-            try
-            {
-               Lock wlock = lock_.writeLock();
-               if (!wlock.tryLock(msecs, TimeUnit.MILLISECONDS))
-               {
-                  String str = caseNum + "-" + name + "-WL-0";
-                  postLockingResult(str);
-                  return;
-               }
-               // OK, write lock obtained, sleep and release it.
-               String str = caseNum + "-" + name + "-WL-1";
-               postLockingResult(str);
-               TestingUtil.sleepThread(sleepSecs);
+     public void run()
+       {
+          Lock rlock = lock_.readLock();
+          try
+          {
+             if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
+             {
+                String str = caseNum + "-" + name + "-RL-0";
+                postLockingResult(str);
+                processNotifications();
+                return;
+             }
+             // OK, read lock obtained, sleep and release it.
+             String str = caseNum + "-" + name + "-RL-1";
+             postLockingResult(str);
+             processNotifications();
 
-               if (secondOP == INVOKE_READ)
-               {
-                  acquireReadLock(caseNum, name, msecs, errMsg);
-               }
-               else if (secondOP == INVOKE_WRITE)
-               {
-                  acquireWriteLock(caseNum, name, msecs, errMsg);
-               }
-               else if (secondOP == INVOKE_UPGRADE)
-               {
-                  acquireUpgradeLock(caseNum, name, msecs, errMsg);
-               }
+             if (secondOP == INVOKE_READ)
+             {
+                acquireReadLock(caseNum, name, errMsg);
+             }
+             else if (secondOP == INVOKE_WRITE)
+             {
+                acquireWriteLock(caseNum, name, errMsg);
+             }
+             else if (secondOP == INVOKE_UPGRADE)
+             {
+                acquireUpgradeLock(caseNum, name, errMsg);
+             }
+             rlock.unlock();
+             notifyBeforeFinish.countDown();
+          }
+          catch (Exception ex)
+          {
+          }
+       }
 
-               wlock.unlock();
-            }
-            catch (Exception ex)
-            {
-               ex.printStackTrace();
-            }
-         }
-      };
+     private void processNotifications() throws InterruptedException {
+       notifyBeforeSecondOp.countDown();
+       if (waitLatch != null) waitLatch.await(10, TimeUnit.SECONDS);
+     }
    }
 
-   /**
-    * Creates a new thread, acquires a read lock, sleeps for a while
-    * and then tries to upgrade the read lock to a write one. Similar
-    * to {@link #readThread readThread()} except it's used for upgrading
-    * locks.
-    *
-    * @see #readThread readThread()
-    */
-   protected Thread upgradeThread(final String caseNum, final String name,
-                                  final long msecs, final String errMsg)
-   {
-      return new Thread(name)
-      {
-         public void run()
-         {
-            try
-            {
-               Lock rlock = lock_.readLock();
-               Lock wlock = null;
-               if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
-               {
-                  String str = caseNum + "-" + name + "-RL-0";
-                  postLockingResult(str);
-                  return;
-               }
-               // OK, read lock obtained, sleep and upgrade it later.
-               TestingUtil.sleepThread(SLEEP_MSECS / 2);
-               String str = caseNum + "-" + name + "-UL-";
-               if ((wlock = lock_.upgradeLockAttempt(msecs)) == null)
-               {
-                  str += "0";
-               }
-               else
-               {
-                  str += "1";
-               }
-               postLockingResult(str);
-               // Sleep again and then release the lock.
-               TestingUtil.sleepThread(SLEEP_MSECS);
-               if (wlock != null)
-               {
-                  wlock.unlock();
-               }
-               rlock.unlock();
-            }
-            catch (Exception ex)
-            {
-            }
-         }
-      };
-   }
+  private class WriteThread extends Thread
+  {
+    String caseNum;
+    String name;
+    volatile CountDownLatch notifyLatch = new CountDownLatch(1);
+    volatile CountDownLatch waitLatch;
+    String errMsg;
+    int secondOP;
 
+    WriteThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch waitLatch) {
+      this.caseNum = caseNum;
+      this.name = name;
+      this.errMsg = errMsg;
+      this.secondOP = secondOP;
+      this.waitLatch = waitLatch;
+    }
+
+
+    public void run()
+    {
+       try
+       {
+          Lock wlock = lock_.writeLock();
+          if (!wlock.tryLock(0, TimeUnit.MILLISECONDS))
+          {
+             String str = caseNum + "-" + name + "-WL-0";
+             postLockingResult(str);
+             processNotifications();
+             return;
+          }
+          // OK, write lock obtained, sleep and release it.
+          String str = caseNum + "-" + name + "-WL-1";
+          postLockingResult(str);
+
+          processNotifications();
+
+          if (secondOP == INVOKE_READ)
+          {
+             acquireReadLock(caseNum, name, errMsg);
+          }
+          else if (secondOP == INVOKE_WRITE)
+          {
+             acquireWriteLock(caseNum, name, errMsg);
+          }
+          else if (secondOP == INVOKE_UPGRADE)
+          {
+             acquireUpgradeLock(caseNum, name, errMsg);
+          }
+
+          wlock.unlock();
+       }
+       catch (Exception ex)
+       {
+          ex.printStackTrace();
+       }
+    }
+
+    private void processNotifications() throws InterruptedException {
+      notifyLatch.countDown();
+      if (waitLatch != null)
+        waitLatch.await(10, TimeUnit.SECONDS);
+    }
+  }
+
+  class UpgradeThread extends Thread
+  {
+    String caseNum;
+    String name;
+    private CountDownLatch notifyBeforeFinish = new CountDownLatch(1);
+    private CountDownLatch notifyBeforeSecondOp = new CountDownLatch(1);
+    private CountDownLatch beforeUpgrateWait;
+    private CountDownLatch beforeFinishWait;
+    String errMsg;
+    int secondOP;
+
+    UpgradeThread(String caseNum, String name, String errMsg, int secondOP, CountDownLatch beforeUpgrateWait) {
+      this.caseNum = caseNum;
+      this.name = name;
+      this.errMsg = errMsg;
+      this.secondOP = secondOP;
+      this.beforeUpgrateWait = beforeUpgrateWait;
+    }
+
+    public void run()
+    {
+       try
+       {
+          Lock rlock = lock_.readLock();
+          Lock wlock;
+          if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
+          {
+             String str = caseNum + "-" + name + "-RL-0";
+             postLockingResult(str);
+             notifyBeforeFinish.countDown();
+            if (beforeUpgrateWait != null) beforeUpgrateWait.await(10, TimeUnit.SECONDS);
+            return;
+          }
+          // OK, read lock obtained, sleep and upgrade it later.
+          notifyBeforeSecondOp.countDown();
+          if (beforeUpgrateWait != null) beforeUpgrateWait.await(10, TimeUnit.SECONDS);
+          String str = caseNum + "-" + name + "-UL-";
+          if ((wlock = lock_.upgradeLockAttempt(0)) == null)
+          {
+             str += "0";
+          }
+          else
+          {
+             str += "1";
+          }
+          postLockingResult(str);
+          // Sleep again and then release the lock.
+          TestingUtil.sleepThread(SLEEP_MSECS);
+          if (wlock != null)
+          {
+             wlock.unlock();
+          }
+          rlock.unlock();
+          notifyBeforeFinish.countDown();
+          if (beforeFinishWait != null) beforeFinishWait.await(10, TimeUnit.SECONDS);
+       }
+       catch (Exception ex)
+       {
+       }
+    }
+
+  }
+
+
    /***************************************************************/
    /*     Utility functions to acquire RL and WL (no thread)      */
    /***************************************************************/
    /**
     * This routine tries to acquire a read lock with a timeout value
-    * passed in by the caller. Like {@link #readThread readThread()}
-    * it then stores the locking result in the result vector depending
+    * passed in by the caller. It then stores the locking result in the result vector depending
     * on the outcome of the request.
     */
 
    protected void acquireReadLock(final String caseNum, final String name,
-                                  final long msecs, final String errMsg)
+                                  final String errMsg)
    {
       try
       {
          Lock rlock = lock_.readLock();
-         if (!rlock.tryLock(msecs, TimeUnit.MILLISECONDS))
+         if (!rlock.tryLock(0, TimeUnit.MILLISECONDS))
          {
             String str = caseNum + "-" + name + "-RL-0";
             postLockingResult(str);
@@ -279,13 +311,12 @@
     * Same as {@link #acquireReadLock acquireReadLock()} except
     * it's for write lock request.
     */
-   protected void acquireWriteLock(final String caseNum, final String name,
-                                   final long msecs, final String errMsg)
+   protected void acquireWriteLock(final String caseNum, final String name, final String errMsg)
    {
       try
       {
          Lock wlock = lock_.writeLock();
-         if (!wlock.tryLock(msecs, TimeUnit.MILLISECONDS))
+         if (!wlock.tryLock(0, TimeUnit.MILLISECONDS))
          {
             String str = caseNum + "-" + name + "-WL-0";
             postLockingResult(str);
@@ -307,12 +338,12 @@
     * it's for upgrade lock request.
     */
    protected void acquireUpgradeLock(final String caseNum, final String name,
-                                     final long msecs, final String errMsg)
+                                     final String errMsg)
    {
       try
       {
          Lock ulock = null;
-         if ((ulock = lock_.upgradeLockAttempt(msecs)) == null)
+         if ((ulock = lock_.upgradeLockAttempt(0)) == null)
          {
             String str = caseNum + "-" + name + "-UL-0";
             postLockingResult(str);
@@ -378,10 +409,8 @@
    public void testWriteWithMultipleReaders() throws Exception
    {
       String caseNum = "10";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS * 2,
-              "1st read lock attempt failed", NO_MORE_OP);
-      Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd read lock attempt failed", INVOKE_WRITE);
+      ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, null);
+      ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", INVOKE_WRITE, t1.notifyBeforeSecondOp);
 
       t1.start();
       t2.start();
@@ -404,10 +433,8 @@
    public void testUpgradeWithMultipleReadersOn1() throws Exception
    {
       String caseNum = "11";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st read lock attempt failed", INVOKE_WRITE);
-      Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS * 2,
-              "2nd read lock attempt failed", NO_MORE_OP);
+      ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", INVOKE_WRITE, null);
+      ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, t1.notifyBeforeSecondOp);
 
       t1.start();
       t2.start();
@@ -430,8 +457,7 @@
    public void testUpgradeReadLock() throws Exception
    {
       String caseNum = "2";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st read lock attempt failed", INVOKE_UPGRADE);
+      Thread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", INVOKE_UPGRADE, null);
 
       t1.start();
       t1.join(3000);
@@ -443,12 +469,11 @@
    /**
     * Case #3 - T1 acquires RL followed by WL.
     */
-
    public void testReadThenWrite() throws Exception
    {
       String caseNum = "3";
-      acquireReadLock(caseNum, "t1", 0, "1st read lock attempt failed");
-      acquireWriteLock(caseNum, "t1.1", 0, "2nd write lock attempt failed");
+      acquireReadLock(caseNum, "t1", "1st read lock attempt failed");
+      acquireWriteLock(caseNum, "t1.1", "2nd write lock attempt failed");
       assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&
               checkLockingResult(caseNum + "-t1.1-WL-1"));
       cleanLockingResult();
@@ -458,12 +483,11 @@
    /**
     * Case #5 - T1 acquires WL followed by RL.
     */
-
    public void testWriteThenRead() throws Exception
    {
       String caseNum = "5";
-      acquireWriteLock(caseNum, "t1", 0, "1st write lock attempt failed");
-      acquireReadLock(caseNum, "t1.1", 0, "2nd read lock attempt failed");
+      acquireWriteLock(caseNum, "t1", "1st write lock attempt failed");
+      acquireReadLock(caseNum, "t1.1", "2nd read lock attempt failed");
       assertTrue(checkLockingResult(caseNum + "-t1-WL-1") &&
               checkLockingResult(caseNum + "-t1.1-RL-1"));
       cleanLockingResult();
@@ -475,10 +499,8 @@
    public void testMultipleReadlock() throws Exception
    {
       String caseNum = "6";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st read lock attempt failed", NO_MORE_OP);
-      Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd read lock attempt failed", NO_MORE_OP);
+      Thread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, null);
+      Thread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, null);
 
       t1.start();
       t2.start();
@@ -500,16 +522,22 @@
    public void testWriteWithExistingReader() throws Exception
    {
       String caseNum = "8";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st write lock attempt failed", NO_MORE_OP);
-      Thread t2 = writeThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd read lock attempt failed", NO_MORE_OP);
+      CountDownLatch waitFor = new CountDownLatch(1);
+      ReadThread t1 = new ReadThread(caseNum, "t1",   "1st write lock attempt failed", NO_MORE_OP, waitFor);
+      WriteThread t2 = new WriteThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, waitFor);
 
       t1.start();
       t2.start();
+
+      t1.notifyBeforeSecondOp.await();
+      t2.notifyLatch.await();
+      waitFor.countDown();
+
+      waitFor.countDown();
       t1.join(3000);
       t2.join(3000);
 
+
       // there is NO guarantee as to which thread will get the lock!!
       boolean t0GetsLock = checkLockingResult(caseNum + "-t1-RL-1") && checkLockingResult(caseNum + "-t2-WL-0");
       boolean t1GetsLock = checkLockingResult(caseNum + "-t1-RL-0") && checkLockingResult(caseNum + "-t2-WL-1");
@@ -531,13 +559,17 @@
    public void testReadWithExistingWriter() throws Exception
    {
       String caseNum = "13";
-      Thread t1 = writeThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st write lock attempt failed", NO_MORE_OP);
-      Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd read lock attempt failed", NO_MORE_OP);
+      CountDownLatch waitFor = new CountDownLatch(1);
+      WriteThread t1 = new WriteThread(caseNum, "t1", "1st write lock attempt failed", NO_MORE_OP, waitFor);
+      ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", NO_MORE_OP, waitFor);
 
       t1.start();
       t2.start();
+
+      t1.notifyLatch.await();
+      t2.notifyBeforeSecondOp.await();
+      waitFor.countDown();
+
       t1.join(3000);
       t2.join(3000);
 
@@ -562,13 +594,16 @@
    public void testMultipleWritelocks() throws Exception
    {
       String caseNum = "14";
-      Thread t1 = writeThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st write lock attempt failed", NO_MORE_OP);
-      Thread t2 = writeThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd write lock attempt failed", NO_MORE_OP);
+      CountDownLatch waitFor = new CountDownLatch(1);
+      WriteThread t1 = new WriteThread(caseNum, "t1", "1st write lock attempt failed", NO_MORE_OP, waitFor);
+      WriteThread t2 = new WriteThread(caseNum, "t2", "2nd write lock attempt failed", NO_MORE_OP, waitFor);
 
       t1.start();
       t2.start();
+      t1.notifyLatch.await();
+      t2.notifyLatch.await();
+      waitFor.countDown();
+
       t1.join(3000);
       t2.join(3000);
 
@@ -590,21 +625,23 @@
    /**
     * Case #7 - T1 acquires RL, T2 acquires UL.
     */
-
    public void testUpgradeWithExistingReader() throws Exception
    {
       String caseNum = "7";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS,
-              "1st read lock attempt failed", NO_MORE_OP);
-      Thread t2 = upgradeThread(caseNum, "t2", 0,
-              "2nd upgrade lock attempt failed");
+      CountDownLatch waitFor = new CountDownLatch(1);
+      ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, waitFor);
+      UpgradeThread t2 = new UpgradeThread(caseNum, "t2", "2nd upgrade lock attempt failed", NO_MORE_OP, t1.notifyBeforeSecondOp);
+      t2.beforeFinishWait = waitFor;
 
       t1.start();
       t2.start();
+      t2.notifyBeforeFinish.await(10, TimeUnit.SECONDS);
+      waitFor.countDown();
+
       t1.join(3000);
       t2.join(3000);
-      assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&
-              checkLockingResult(caseNum + "-t2-UL-0"));
+      assertTrue(checkLockingResult(caseNum + "-t1-RL-1"));
+      assertTrue(checkLockingResult(caseNum + "-t2-UL-0"));
       cleanLockingResult();
       // possilbe deadlock check
       if (t1.isAlive() || t2.isAlive())
@@ -619,13 +656,17 @@
    public void testUpgradeWithMultipleReaders() throws Exception
    {
       String caseNum = "9";
-      Thread t1 = readThread(caseNum, "t1", 0, SLEEP_MSECS * 2,
-              "1st read lock attempt failed", NO_MORE_OP);
-      Thread t2 = readThread(caseNum, "t2", 0, SLEEP_MSECS,
-              "2nd read lock attempt failed", INVOKE_UPGRADE);
+      CountDownLatch waitFor = new CountDownLatch(1);
+      ReadThread t1 = new ReadThread(caseNum, "t1", "1st read lock attempt failed", NO_MORE_OP, waitFor);
+      ReadThread t2 = new ReadThread(caseNum, "t2", "2nd read lock attempt failed", INVOKE_UPGRADE, t1.notifyBeforeSecondOp);
 
       t1.start();
       t2.start();
+
+      t1.notifyBeforeSecondOp.await(10, TimeUnit.SECONDS);
+      t2.notifyBeforeFinish.await(10, TimeUnit.SECONDS);
+      waitFor.countDown();
+
       t1.join(3000);
       t2.join(3000);
       assertTrue(checkLockingResult(caseNum + "-t1-RL-1") &&




More information about the jbosscache-commits mailing list