--- jsr166/src/test/tck/ThreadLocalTest.java 2003/08/31 19:24:56 1.1 +++ jsr166/src/test/tck/ThreadLocalTest.java 2009/08/04 10:13:48 1.7 @@ -1,14 +1,15 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; import java.util.concurrent.Semaphore; -public class ThreadLocalTest extends TestCase { +public class ThreadLocalTest extends JSR166TestCase { public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } @@ -17,21 +18,88 @@ public class ThreadLocalTest extends Tes return new TestSuite(ThreadLocalTest.class); } - static ThreadLocal tl = new ThreadLocal() { - public Object initialValue() { - return new Integer(1); + static ThreadLocal tl = new ThreadLocal() { + public Integer initialValue() { + return one; } }; - + static InheritableThreadLocal itl = + new InheritableThreadLocal() { + protected Integer initialValue() { + return zero; + } + + protected Integer childValue(Integer parentValue) { + return new Integer(parentValue.intValue() + 1); + } + }; + + /** + * remove causes next access to return initial value + */ public void testRemove() { - Integer one = new Integer(1); - Integer two = new Integer(2); assertEquals(tl.get(), one); tl.set(two); assertEquals(tl.get(), two); tl.remove(); assertEquals(tl.get(), one); } -} + /** + * remove in InheritableThreadLocal causes next access to return + * initial value + */ + public void testRemoveITL() { + assertEquals(itl.get(), zero); + itl.set(two); + assertEquals(itl.get(), two); + itl.remove(); + assertEquals(itl.get(), zero); + } + + private class ITLThread extends Thread { + final int[] x; + ITLThread(int[] array) { x = array; } + public void run() { + Thread child = null; + if (itl.get().intValue() < x.length - 1) { + child = new ITLThread(x); + child.start(); + } + Thread.currentThread().yield(); + + int threadId = itl.get().intValue(); + for (int j = 0; j < threadId; j++) { + x[threadId]++; + Thread.currentThread().yield(); + } + + if (child != null) { // Wait for child (if any) + try { + child.join(); + } catch (InterruptedException e) { + threadUnexpectedException(e); + } + } + } + } + + /** + * InheritableThreadLocal propagates generic values. + */ + public void testGenericITL() { + final int threadCount = 10; + final int x[] = new int[threadCount]; + Thread progenitor = new ITLThread(x); + try { + progenitor.start(); + progenitor.join(); + for (int i = 0; i < threadCount; i++) { + assertEquals(i, x[i]); + } + } catch (InterruptedException e) { + unexpectedException(e); + } + } +}