@Override public final void close() throws IOException { try { if (buffers == null) return; // make local copy, then un-set early final ByteBuffer[] bufs = buffers; unsetBuffers(); if (clones != null) { clones.remove(this); } if (isClone) return; // for extra safety unset also all clones' buffers: if (clones != null) { for (Iterator<ByteBufferIndexInput> it = this.clones.keyIterator(); it.hasNext(); ) { final ByteBufferIndexInput clone = it.next(); assert clone.isClone; clone.unsetBuffers(); } this.clones.clear(); } for (final ByteBuffer b : bufs) { freeBuffer(b); } } finally { unsetBuffers(); } }
public void testSimpleHashMap() { final WeakIdentityMap<String, String> map = WeakIdentityMap.newHashMap(random().nextBoolean()); // we keep strong references to the keys, // so WeakIdentityMap will not forget about them: String key1 = new String("foo"); String key2 = new String("foo"); String key3 = new String("foo"); assertNotSame(key1, key2); assertEquals(key1, key2); assertNotSame(key1, key3); assertEquals(key1, key3); assertNotSame(key2, key3); assertEquals(key2, key3); // try null key & check its iterator also return null: map.put(null, "null"); { Iterator<String> it = map.keyIterator(); assertTrue(it.hasNext()); assertNull(it.next()); assertFalse(it.hasNext()); assertFalse(it.hasNext()); } // 2 more keys: map.put(key1, "bar1"); map.put(key2, "bar2"); assertEquals(3, map.size()); assertEquals("bar1", map.get(key1)); assertEquals("bar2", map.get(key2)); assertEquals(null, map.get(key3)); assertEquals("null", map.get(null)); assertTrue(map.containsKey(key1)); assertTrue(map.containsKey(key2)); assertFalse(map.containsKey(key3)); assertTrue(map.containsKey(null)); // repeat and check that we have no double entries map.put(key1, "bar1"); map.put(key2, "bar2"); map.put(null, "null"); assertEquals(3, map.size()); assertEquals("bar1", map.get(key1)); assertEquals("bar2", map.get(key2)); assertEquals(null, map.get(key3)); assertEquals("null", map.get(null)); assertTrue(map.containsKey(key1)); assertTrue(map.containsKey(key2)); assertFalse(map.containsKey(key3)); assertTrue(map.containsKey(null)); map.remove(null); assertEquals(2, map.size()); map.remove(key1); assertEquals(1, map.size()); map.put(key1, "bar1"); map.put(key2, "bar2"); map.put(key3, "bar3"); assertEquals(3, map.size()); int c = 0, keysAssigned = 0; for (Iterator<String> it = map.keyIterator(); it.hasNext(); ) { assertTrue(it.hasNext()); // try again, should return same result! final String k = it.next(); assertTrue(k == key1 || k == key2 | k == key3); keysAssigned += (k == key1) ? 1 : ((k == key2) ? 2 : 4); c++; } assertEquals(3, c); assertEquals("all keys must have been seen", 1 + 2 + 4, keysAssigned); c = 0; for (Iterator<String> it = map.valueIterator(); it.hasNext(); ) { final String v = it.next(); assertTrue(v.startsWith("bar")); c++; } assertEquals(3, c); // clear strong refs key1 = key2 = key3 = null; // check that GC does not cause problems in reap() method, wait 1 second and let GC work: int size = map.size(); for (int i = 0; size > 0 && i < 10; i++) try { System.runFinalization(); System.gc(); int newSize = map.size(); assertTrue("previousSize(" + size + ")>=newSize(" + newSize + ")", size >= newSize); size = newSize; Thread.sleep(100L); c = 0; for (Iterator<String> it = map.keyIterator(); it.hasNext(); ) { assertNotNull(it.next()); c++; } newSize = map.size(); assertTrue("previousSize(" + size + ")>=iteratorSize(" + c + ")", size >= c); assertTrue("iteratorSize(" + c + ")>=newSize(" + newSize + ")", c >= newSize); size = newSize; } catch (InterruptedException ie) { } map.clear(); assertEquals(0, map.size()); assertTrue(map.isEmpty()); Iterator<String> it = map.keyIterator(); assertFalse(it.hasNext()); try { it.next(); fail("Should throw NoSuchElementException"); } catch (NoSuchElementException nse) { } key1 = new String("foo"); key2 = new String("foo"); map.put(key1, "bar1"); map.put(key2, "bar2"); assertEquals(2, map.size()); map.clear(); assertEquals(0, map.size()); assertTrue(map.isEmpty()); }