Added ability to make referenced value purgable. This allows an instance to be constructed with weak referenced keys whose values are purged when the keys are garbage collected.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131042 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9e9541ec69
commit
1ebd856d1f
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/ReferenceMap.java,v 1.10 2003/05/06 11:19:26 rdonkin Exp $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/ReferenceMap.java,v 1.11 2003/05/07 09:18:57 rdonkin Exp $
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
* The Apache Software License, Version 1.1
|
* The Apache Software License, Version 1.1
|
||||||
|
@ -116,7 +116,7 @@ import java.util.Set;
|
||||||
* @see java.lang.ref.Reference
|
* @see java.lang.ref.Reference
|
||||||
*
|
*
|
||||||
* @since Commons Collections 2.1
|
* @since Commons Collections 2.1
|
||||||
* @version $Revision: 1.10 $ $Date: 2003/05/06 11:19:26 $
|
* @version $Revision: 1.11 $ $Date: 2003/05/07 09:18:57 $
|
||||||
*
|
*
|
||||||
* @author Paul Jack
|
* @author Paul Jack
|
||||||
*/
|
*/
|
||||||
|
@ -176,6 +176,11 @@ public class ReferenceMap extends AbstractMap {
|
||||||
*/
|
*/
|
||||||
private float loadFactor;
|
private float loadFactor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the value be automatically purged when the associated key has been collected?
|
||||||
|
*/
|
||||||
|
private boolean purgeValues = false;
|
||||||
|
|
||||||
|
|
||||||
// -- Non-serialized instance variables
|
// -- Non-serialized instance variables
|
||||||
|
|
||||||
|
@ -237,6 +242,21 @@ public class ReferenceMap extends AbstractMap {
|
||||||
this(HARD, SOFT);
|
this(HARD, SOFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new <Code>ReferenceMap</Code> that will
|
||||||
|
* use the specified types of references.
|
||||||
|
*
|
||||||
|
* @param keyType the type of reference to use for keys;
|
||||||
|
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||||
|
* @param valueType the type of reference to use for values;
|
||||||
|
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||||
|
* @param purgeValues should the value be automatically purged when the
|
||||||
|
* key is garbage collected
|
||||||
|
*/
|
||||||
|
public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
|
||||||
|
this(keyType, valueType);
|
||||||
|
this.purgeValues = purgeValues;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new <Code>ReferenceMap</Code> that will
|
* Constructs a new <Code>ReferenceMap</Code> that will
|
||||||
|
@ -251,6 +271,29 @@ public class ReferenceMap extends AbstractMap {
|
||||||
this(keyType, valueType, 16, 0.75f);
|
this(keyType, valueType, 16, 0.75f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new <Code>ReferenceMap</Code> with the
|
||||||
|
* specified reference types, load factor and initial
|
||||||
|
* capacity.
|
||||||
|
*
|
||||||
|
* @param keyType the type of reference to use for keys;
|
||||||
|
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||||
|
* @param valueType the type of reference to use for values;
|
||||||
|
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||||
|
* @param capacity the initial capacity for the map
|
||||||
|
* @param loadFactor the load factor for the map
|
||||||
|
* @param purgeValues should the value be automatically purged when the
|
||||||
|
* key is garbage collected
|
||||||
|
*/
|
||||||
|
public ReferenceMap(
|
||||||
|
int keyType,
|
||||||
|
int valueType,
|
||||||
|
int capacity,
|
||||||
|
float loadFactor,
|
||||||
|
boolean purgeValues) {
|
||||||
|
this(keyType, valueType, capacity, loadFactor);
|
||||||
|
this.purgeValues = purgeValues;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new <Code>ReferenceMap</Code> with the
|
* Constructs a new <Code>ReferenceMap</Code> with the
|
||||||
|
@ -778,7 +821,11 @@ public class ReferenceMap extends AbstractMap {
|
||||||
r = r || ((valueType > HARD) && (value == ref));
|
r = r || ((valueType > HARD) && (value == ref));
|
||||||
if (r) {
|
if (r) {
|
||||||
if (keyType > HARD) ((Reference)key).clear();
|
if (keyType > HARD) ((Reference)key).clear();
|
||||||
if (valueType > HARD) ((Reference)value).clear();
|
if (valueType > HARD) {
|
||||||
|
((Reference)value).clear();
|
||||||
|
} else if (purgeValues) {
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestReferenceMap.java,v 1.7 2003/05/06 11:19:26 rdonkin Exp $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestReferenceMap.java,v 1.8 2003/05/07 09:18:58 rdonkin Exp $
|
||||||
* $Revision: 1.7 $
|
* $Revision: 1.8 $
|
||||||
* $Date: 2003/05/06 11:19:26 $
|
* $Date: 2003/05/07 09:18:58 $
|
||||||
*
|
*
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
|
@ -61,6 +61,8 @@
|
||||||
|
|
||||||
package org.apache.commons.collections;
|
package org.apache.commons.collections;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
|
@ -70,7 +72,7 @@ import junit.framework.Test;
|
||||||
* Tests for ReferenceMap.
|
* Tests for ReferenceMap.
|
||||||
*
|
*
|
||||||
* @author Paul Jack
|
* @author Paul Jack
|
||||||
* @version $Id: TestReferenceMap.java,v 1.7 2003/05/06 11:19:26 rdonkin Exp $
|
* @version $Id: TestReferenceMap.java,v 1.8 2003/05/07 09:18:58 rdonkin Exp $
|
||||||
*/
|
*/
|
||||||
public class TestReferenceMap extends TestMap {
|
public class TestReferenceMap extends TestMap {
|
||||||
|
|
||||||
|
@ -186,5 +188,44 @@ public class TestReferenceMap extends TestMap {
|
||||||
return "2.1";
|
return "2.1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Tests whether purge values setting works */
|
||||||
|
public void testPurgeValues() throws Exception {
|
||||||
|
// many thanks to Juozas Baliuka for suggesting this method
|
||||||
|
Object key = new Object();
|
||||||
|
Object value = new Object();
|
||||||
|
|
||||||
|
WeakReference keyReference = new WeakReference(key);
|
||||||
|
WeakReference valueReference = new WeakReference(value);
|
||||||
|
|
||||||
|
Map testMap = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
|
||||||
|
testMap.put(key, value);
|
||||||
|
|
||||||
|
assertEquals("In map", value, testMap.get(key));
|
||||||
|
assertNotNull("Weak reference released early (1)", keyReference.get());
|
||||||
|
assertNotNull("Weak reference released early (2)", valueReference.get());
|
||||||
|
|
||||||
|
// dereference strong references
|
||||||
|
key = null;
|
||||||
|
value = null;
|
||||||
|
|
||||||
|
int iterations = 0;
|
||||||
|
int bytz = 2;
|
||||||
|
while(true) {
|
||||||
|
System.gc();
|
||||||
|
if(iterations++ > 50){
|
||||||
|
fail("Max iterations reached before resource released.");
|
||||||
|
}
|
||||||
|
testMap.isEmpty();
|
||||||
|
if(
|
||||||
|
keyReference.get() == null &&
|
||||||
|
valueReference.get() == null) {
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// create garbage:
|
||||||
|
byte[] b = new byte[bytz];
|
||||||
|
bytz = bytz * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue