KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > util > test > ReadWriteLockTest


1 /*
2  * Copyright 2002 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: ReadWriteLockTest.java,v 1.3 2002/11/08 05:06:28 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.util.test;
12
13 import com.triactive.jdo.util.ReadWriteLock;
14 import java.util.Random JavaDoc;
15 import junit.framework.TestCase;
16
17
18 /**
19  * Tests the functionality of a {@link ReadWriteLock}.
20  *
21  * @author <a HREF="mailto:mmartin5@austin.rr.com">Mike Martin</a>
22  * @version $Revision: 1.3 $
23  */

24
25 public class ReadWriteLockTest extends TestCase
26 {
27     private static final int MAX_TEST_TIME = 30;
28     private static final int NUM_TEST_THREADS = 10;
29     private static final int NUM_OUTER_ITERATIONS = 500;
30     private static final int NUM_INNER_ITERATIONS = 2500;
31     private static final int YIELD_FREQUENCY = 250;
32
33     private Throwable JavaDoc threadFailure;
34
35
36     /**
37      * Used by the JUnit framework to construct tests. Normally, programmers
38      * would never explicitly use this constructor.
39      *
40      * @param name Name of the <tt>TestCase</tt>.
41      */

42
43     public ReadWriteLockTest(String JavaDoc name)
44     {
45         super(name);
46     }
47
48
49     public void testBasicFunction() throws Throwable JavaDoc
50     {
51         ThreadGroup JavaDoc group = new ThreadGroup JavaDoc("ReadWriteLockTest");
52         Thread JavaDoc[] threads = new Thread JavaDoc[NUM_TEST_THREADS];
53         ReadWriteLock rwl = new ReadWriteLock();
54         Object JavaDoc[] objs = new Object JavaDoc[1];
55
56         /*
57          * Create and start all the threads running the test.
58          */

59         for (int i = 0; i < NUM_TEST_THREADS; ++i)
60             threads[i] = new Thread JavaDoc(group, new TestThread(new Random JavaDoc(i), rwl, objs), "Test thread #" + i);
61
62         threadFailure = null;
63
64         for (int i = 0; i < NUM_TEST_THREADS; ++i)
65             threads[i].start();
66
67         /*
68          * Wait up to MAX_TEST_TIME seconds for all threads to finish. Any
69          * longer is assumed to be a failure.
70          */

71         long startTime = System.currentTimeMillis();
72         int runningThreads;
73
74         do
75         {
76             runningThreads = group.enumerate(threads);
77
78             for (int i = 0; i < runningThreads; ++i)
79             {
80                 threads[i].join(250);
81
82                 if (System.currentTimeMillis() - startTime > MAX_TEST_TIME * 1000)
83                 {
84                     for (int j = 0; j < runningThreads; ++j)
85                         threads[j].interrupt();
86
87                     fail("Test has taken more than " + MAX_TEST_TIME + " seconds; it is assumed to be deadlocked");
88                 }
89             }
90         } while (runningThreads > 0);
91
92         /*
93          * If any thread threw an exception, rethrow the last one that
94          * occurred.
95          */

96         if (threadFailure != null)
97             throw threadFailure;
98     }
99
100
101     private class TestThread implements Runnable JavaDoc
102     {
103         private final Random JavaDoc rnd;
104         private final ReadWriteLock rwl;
105         private final Object JavaDoc[] objs;
106
107         public TestThread(Random JavaDoc rnd, ReadWriteLock rwl, Object JavaDoc[] objs)
108         {
109             this.rnd = rnd;
110             this.rwl = rwl;
111             this.objs = objs;
112         }
113
114
115         public void run()
116         {
117             try
118             {
119                 /*
120                  * Test various legal and illegal nested locking patterns
121                  * repeatedly in a random order.
122                  */

123                 final String JavaDoc[] lockPatterns =
124                     {
125                         /* Legal patterns */
126                         "R", "W",
127                         "RR", "WR", "WW",
128                         "RRR", "WRR", "WWR", "WWW",
129
130                         /* Illegal patterns */
131                         "RW", "RRW", "RRRW", "RRRRW"
132                     };
133
134                 for (int i = 0; i < NUM_OUTER_ITERATIONS && threadFailure == null; ++i)
135                 {
136                     String JavaDoc pattern = lockPatterns[rnd.nextInt(lockPatterns.length)];
137                     boolean isLegalPattern = pattern.indexOf("RW") == -1;
138
139                     try
140                     {
141                         tryPattern(pattern);
142
143                         if (!isLegalPattern)
144                             fail("Illegal nested lock sequence " + pattern + " should have thrown an IllegalStateException");
145                     }
146                     catch (IllegalStateException JavaDoc e)
147                     {
148                         if (isLegalPattern)
149                             throw e;
150                     }
151                 }
152             }
153             catch (Throwable JavaDoc t)
154             {
155                 threadFailure = t;
156             }
157         }
158
159
160         private void tryPattern(String JavaDoc lockPattern) throws InterruptedException JavaDoc
161         {
162             boolean isWriteLock = lockPattern.charAt(0) == 'W';
163
164             if (isWriteLock)
165                 rwl.writeLock();
166             else
167                 rwl.readLock();
168
169             try
170             {
171                 Object JavaDoc obj;
172
173                 /*
174                  * If writing, assign a new value to the array, else read the
175                  * existing value.
176                  */

177                 if (isWriteLock)
178                 {
179                     obj = this;
180                     objs[0] = obj;
181                 }
182                 else
183                     obj = objs[0];
184
185                 /*
186                  * Assert that the current value doesn't change over many
187                  * successive accesses. Occasionally yield to other threads.
188                  */

189                 for (int i = 0; i < NUM_INNER_ITERATIONS; ++i)
190                 {
191                     ReadWriteLockTest.this.assertSame(obj, objs[0]);
192
193                     if (i % YIELD_FREQUENCY == 0)
194                         Thread.yield();
195                 }
196
197                 /*
198                  * If the pattern calls for nested locks, recurse.
199                  */

200                 if (lockPattern.length() > 1)
201                     tryPattern(lockPattern.substring(1));
202             }
203             finally
204             {
205                 rwl.unlock();
206             }
207         }
208     }
209 }
210
Popular Tags