mirror of https://github.com/apache/openjpa.git
Simplify algorithm in NullSafeConcurrentHashMap; change SizedConcurrentHashMap's algorithms to remove overflow before putting new records into cache instead of after to avoid removing the very instances that were put.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/1.1.x@652930 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d8b82311f5
commit
c9fd781007
|
@ -83,20 +83,21 @@ public class NullSafeConcurrentHashMap extends ConcurrentHashMap {
|
|||
// as other threads remove the same entries, whereas the random
|
||||
// iterator may return values that have been removed.
|
||||
|
||||
while (!isEmpty()) {
|
||||
while (!randomKeys.isEmpty()) {
|
||||
// randomKeys contains null-masked data
|
||||
Iterator iter = randomKeys.iterator();
|
||||
Object key = iter.next();
|
||||
if (key != null && randomKeys.remove(key)) {
|
||||
Object val = super.remove(key);
|
||||
if (val != null)
|
||||
return new EntryImpl(unmaskNull(key), unmaskNull(val));
|
||||
}
|
||||
for (Iterator iter = randomKeys.iterator(); iter.hasNext(); ) {
|
||||
// randomKeys contains null-masked data
|
||||
Object key = iter.next();
|
||||
if (key != null && randomKeys.remove(key)) {
|
||||
Object val = super.remove(key);
|
||||
if (val != null)
|
||||
return new EntryImpl(unmaskNull(key), unmaskNull(val));
|
||||
}
|
||||
}
|
||||
|
||||
// if randomKeys is empty, fall back to non-random behavior.
|
||||
Object key = super.keySet().iterator().next();
|
||||
// if randomKeys is empty, fall back to non-random behavior.
|
||||
for (Iterator iter = super.keySet().iterator(); iter.hasNext(); ) {
|
||||
Object key = iter.next();
|
||||
if (key == null)
|
||||
continue;
|
||||
Object val = super.remove(key);
|
||||
if (val != null)
|
||||
return new EntryImpl(unmaskNull(key), unmaskNull(val));
|
||||
|
|
|
@ -56,18 +56,16 @@ public class SizedConcurrentHashMap
|
|||
|
||||
@Override
|
||||
public Object putIfAbsent(Object key, Object value) {
|
||||
Object o = super.putIfAbsent(key, value);
|
||||
if (maxSize != Integer.MAX_VALUE)
|
||||
removeOverflow();
|
||||
return o;
|
||||
removeOverflow(true);
|
||||
return super.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object put(Object key, Object value) {
|
||||
Object o = super.put(key, value);
|
||||
if (maxSize != Integer.MAX_VALUE)
|
||||
removeOverflow();
|
||||
return o;
|
||||
removeOverflow(true);
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
|
@ -79,11 +77,23 @@ public class SizedConcurrentHashMap
|
|||
throw new IllegalArgumentException(String.valueOf(max));
|
||||
maxSize = max;
|
||||
|
||||
removeOverflow();
|
||||
removeOverflow(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to <code>removeOverflow(false)</code>.
|
||||
*/
|
||||
protected void removeOverflow() {
|
||||
while (size() > maxSize) {
|
||||
removeOverflow(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes overflow. If <code>forPut</code> is <code>true</code>, then
|
||||
* this uses <code>size() + 1</code> when computing size.
|
||||
*/
|
||||
protected void removeOverflow(boolean forPut) {
|
||||
int sizeToCompareTo = forPut ? maxSize - 1 : maxSize;
|
||||
while (size() > sizeToCompareTo) {
|
||||
Entry entry = removeRandom();
|
||||
// if removeRandom() returns null, break out of the loop. Of course,
|
||||
// since we're not locking, the size might not actually be null
|
||||
|
|
Loading…
Reference in New Issue