1/* 2 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @summary Basic functional test of remove method for InheritableThreadLocal 27 * @author Seetharama Avadhanam 28 */ 29 30public class ITLRemoveTest { 31 private static final int INITIAL_VALUE = Integer.MIN_VALUE; 32 private static final int REMOVE_SET_VALUE = Integer.MAX_VALUE; 33 34 static InheritableThreadLocal<Integer> n = new InheritableThreadLocal<Integer>() { 35 protected Integer initialValue() { 36 return INITIAL_VALUE; 37 } 38 39 protected Integer childValue(Integer parentValue) { 40 return(parentValue + 1); 41 } 42 }; 43 44 static int threadCount = 100; 45 static int x[]; 46 static Throwable exceptions[]; 47 static final int[] removeNode = {10,20,45,38,88}; 48 /* ThreadLocal values will be removed for these threads. */ 49 static final int[] removeAndSet = {12,34,10}; 50 /* ThreadLocal values will be removed and sets new values */ 51 52 public static void main(String args[]) throws Throwable { 53 x = new int[threadCount]; 54 exceptions = new Throwable[threadCount]; 55 56 Thread progenitor = new MyThread(); 57 progenitor.start(); 58 59 // Wait for *all* threads to complete 60 progenitor.join(); 61 62 for(int i = 0; i<threadCount; i++){ 63 int checkValue = i+INITIAL_VALUE; 64 65 /* If the remove method is called then the ThreadLocal value will 66 * be its initial value */ 67 for(int removeId : removeNode) 68 if(removeId == i){ 69 checkValue = INITIAL_VALUE; 70 break; 71 } 72 73 for(int removeId : removeAndSet) 74 if(removeId == i){ 75 checkValue = REMOVE_SET_VALUE; 76 break; 77 } 78 79 if(exceptions[i] != null) 80 throw(exceptions[i]); 81 if(x[i] != checkValue) 82 throw(new Throwable("x[" + i + "] =" + x[i])); 83 } 84 } 85 private static class MyThread extends Thread { 86 public void run() { 87 88 Thread child = null; 89 int threadId=0; 90 try{ 91 threadId = n.get(); 92 // Creating child thread... 93 if (threadId < (threadCount-1+INITIAL_VALUE)) { 94 child = new MyThread(); 95 child.start(); 96 } 97 98 for (int j = 0; j<threadId; j++) 99 Thread.currentThread().yield(); 100 101 102 // To remove the ThreadLocal value... 103 for(int removeId : removeNode) 104 if((threadId-INITIAL_VALUE) == removeId){ 105 n.remove(); 106 break; 107 } 108 109 // To remove the ThreadLocal value and set new value ... 110 for(int removeId : removeAndSet) 111 if((threadId-INITIAL_VALUE) == removeId){ 112 n.remove(); 113 n.set(REMOVE_SET_VALUE); 114 break; 115 } 116 x[threadId-INITIAL_VALUE] = n.get(); 117 }catch(Throwable ex){ 118 exceptions[threadId-INITIAL_VALUE] = ex; 119 } 120 // Wait for child (if any) 121 if (child != null) { 122 try { 123 child.join(); 124 } catch(InterruptedException e) { 125 throw(new RuntimeException("Interrupted")); 126 } 127 } 128 } 129 } 130} 131