ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/jtreg/util/WeakHashMap/GCDuringIteration.java
Revision: 1.3
Committed: Wed Nov 17 17:52:29 2010 UTC (13 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +22 -26 lines
Log Message:
waitForFinalizersToRun

File Contents

# User Rev Content
1 jsr166 1.1 /*
2 jsr166 1.2 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3 jsr166 1.1 * 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 jsr166 1.2 * 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 jsr166 1.1 */
23    
24     /*
25     * @test
26     * @bug 6499848
27     * @ignore until 6842353 is resolved
28     * @summary Check that iterators work properly in the presence of
29     * concurrent finalization and removal of elements.
30     */
31    
32     import java.util.*;
33     import java.util.concurrent.CountDownLatch;
34    
35     public class GCDuringIteration {
36 jsr166 1.3 private static void waitForFinalizersToRun() {
37     for (int i = 0; i < 2; i++) {
38     System.gc();
39     final CountDownLatch fin = new CountDownLatch(1);
40     new Object() { protected void finalize() { fin.countDown(); }};
41     System.gc();
42     try { fin.await(); }
43     catch (InterruptedException ie) { throw new Error(ie); }
44     }
45 jsr166 1.1 }
46    
47     // A class with the traditional pessimal hashCode implementation,
48     // to ensure that all instances end up in the same bucket.
49     static class Foo { public int hashCode() { return 42; }}
50    
51     <K,V> void put(Map<K,V> map, K k, V v) {
52     check(! map.containsKey(k));
53     equal(map.get(k), null);
54     equal(map.put(k, v), null);
55     equal(map.get(k), v);
56     check(map.containsKey(k));
57     equal(map.put(k, v), v);
58     equal(map.get(k), v);
59     check(map.containsKey(k));
60     check(! map.isEmpty());
61     equal(map.keySet().iterator().next(), k);
62     equal(map.values().iterator().next(), v);
63     }
64    
65     void checkIterator(final Iterator<Map.Entry<Foo, Integer>> it, int first) {
66     final Random rnd = new Random();
67     for (int i = first; i >= 0; --i) {
68     if (rnd.nextBoolean()) check(it.hasNext());
69     equal(it.next().getValue(), i);
70     }
71     if (rnd.nextBoolean())
72     THROWS(NoSuchElementException.class,
73     new F(){void f(){it.next();}});
74     if (rnd.nextBoolean())
75     check(! it.hasNext());
76     }
77    
78     <K,V> V firstValue(Map<K,V> map) {
79     return map.values().iterator().next();
80     }
81    
82     void test(String[] args) throws Throwable {
83     final int n = 10;
84     // Create array of strong refs
85     final Foo[] foos = new Foo[2*n];
86     final Map<Foo,Integer> map = new WeakHashMap<Foo,Integer>(foos.length);
87     check(map.isEmpty());
88     equal(map.size(), 0);
89    
90     for (int i = 0; i < foos.length; i++) {
91     Foo foo = new Foo();
92     foos[i] = foo;
93     put(map, foo, i);
94     }
95     equal(map.size(), foos.length);
96    
97     {
98     int first = firstValue(map);
99     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
100 jsr166 1.3 foos[first] = null; waitForFinalizersToRun();
101 jsr166 1.1 equal(map.size(), first);
102     checkIterator(it, first-1);
103     equal(map.size(), first);
104     equal(firstValue(map), first-1);
105     }
106    
107     {
108     int first = firstValue(map);
109     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
110     it.next(); // protects first entry
111     System.out.println(map.values());
112 jsr166 1.3 foos[first] = null; waitForFinalizersToRun();
113 jsr166 1.1 equal(map.size(), first+1);
114     System.out.println(map.values());
115     checkIterator(it, first-1);
116 jsr166 1.3 waitForFinalizersToRun(); // first entry no longer protected
117 jsr166 1.1 equal(map.size(), first);
118     equal(firstValue(map), first-1);
119     }
120    
121     {
122     int first = firstValue(map);
123     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
124     it.next(); // protects first entry
125     System.out.println(map.values());
126 jsr166 1.3 foos[first] = foos[first-1] = null; waitForFinalizersToRun();
127 jsr166 1.1 equal(map.size(), first);
128     equal(firstValue(map), first);
129     System.out.println(map.values());
130     checkIterator(it, first-2);
131 jsr166 1.3 waitForFinalizersToRun(); // first entry no longer protected
132 jsr166 1.1 equal(map.size(), first-1);
133     equal(firstValue(map), first-2);
134     }
135    
136     {
137     int first = firstValue(map);
138     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
139     it.next(); // protects first entry
140     it.hasNext(); // protects second entry
141     System.out.println(map.values());
142 jsr166 1.3 foos[first] = foos[first-1] = null; waitForFinalizersToRun();
143 jsr166 1.1 equal(firstValue(map), first);
144     equal(map.size(), first+1);
145     System.out.println(map.values());
146     checkIterator(it, first-1);
147 jsr166 1.3 waitForFinalizersToRun(); // first entry no longer protected
148 jsr166 1.1 equal(map.size(), first-1);
149     equal(firstValue(map), first-2);
150     }
151    
152     {
153     int first = firstValue(map);
154     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
155     it.next(); // protects first entry
156     System.out.println(map.values());
157 jsr166 1.3 foos[first] = foos[first-1] = null; waitForFinalizersToRun();
158 jsr166 1.1 it.remove();
159     equal(firstValue(map), first-2);
160     equal(map.size(), first-1);
161     System.out.println(map.values());
162     checkIterator(it, first-2);
163 jsr166 1.3 waitForFinalizersToRun();
164 jsr166 1.1 equal(map.size(), first-1);
165     equal(firstValue(map), first-2);
166     }
167    
168     {
169     int first = firstValue(map);
170     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
171     it.next(); // protects first entry
172     it.remove();
173     it.hasNext(); // protects second entry
174     System.out.println(map.values());
175 jsr166 1.3 foos[first] = foos[first-1] = null; waitForFinalizersToRun();
176 jsr166 1.1 equal(firstValue(map), first-1);
177     equal(map.size(), first);
178     System.out.println(map.values());
179     checkIterator(it, first-1);
180 jsr166 1.3 waitForFinalizersToRun();
181 jsr166 1.1 equal(map.size(), first-1);
182     equal(firstValue(map), first-2);
183     }
184    
185     {
186     int first = firstValue(map);
187     final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
188     it.hasNext(); // protects first entry
189     Arrays.fill(foos, null);
190 jsr166 1.3 waitForFinalizersToRun();
191 jsr166 1.1 equal(map.size(), 1);
192     System.out.println(map.values());
193     equal(it.next().getValue(), first);
194     check(! it.hasNext());
195 jsr166 1.3 waitForFinalizersToRun();
196 jsr166 1.1 equal(map.size(), 0);
197     check(map.isEmpty());
198     }
199     }
200    
201     //--------------------- Infrastructure ---------------------------
202     volatile int passed = 0, failed = 0;
203     void pass() {passed++;}
204     void fail() {failed++; Thread.dumpStack();}
205     void fail(String msg) {System.err.println(msg); fail();}
206     void unexpected(Throwable t) {failed++; t.printStackTrace();}
207     void check(boolean cond) {if (cond) pass(); else fail();}
208     void equal(Object x, Object y) {
209     if (x == null ? y == null : x.equals(y)) pass();
210     else fail(x + " not equal to " + y);}
211     public static void main(String[] args) throws Throwable {
212     new GCDuringIteration().instanceMain(args);}
213     void instanceMain(String[] args) throws Throwable {
214     try {test(args);} catch (Throwable t) {unexpected(t);}
215     System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
216     if (failed > 0) throw new AssertionError("Some tests failed");}
217     abstract class F {abstract void f() throws Throwable;}
218     void THROWS(Class<? extends Throwable> k, F... fs) {
219     for (F f : fs)
220     try {f.f(); fail("Expected " + k.getName() + " not thrown");}
221     catch (Throwable t) {
222     if (k.isAssignableFrom(t.getClass())) pass();
223     else unexpected(t);}}
224     }