Resending: Hm... the "freeze" terminology seems odd. Why not "lock"?
Gary > > > On Sep 4, 2016 6:33 AM, <rpo...@apache.org> wrote: >> >> Repository: logging-log4j2 >> Updated Branches: >> refs/heads/LOG4J2-1349-gcfree-threadcontext 191c3f958 -> 7615afadd >> >> >> LOG4J2-1349 implement support for freeze() and isFrozen() in OpenHashMapContextData (for MutableContextData interface change) >> >> >> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo >> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/7615afad >> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/7615afad >> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/7615afad >> >> Branch: refs/heads/LOG4J2-1349-gcfree-threadcontext >> Commit: 7615afadd1ba368ed07e8967c270940f624925bb >> Parents: 191c3f9 >> Author: rpopma <rpo...@apache.org> >> Authored: Sun Sep 4 19:33:46 2016 +0900 >> Committer: rpopma <rpo...@apache.org> >> Committed: Sun Sep 4 19:33:46 2016 +0900 >> >> ---------------------------------------------------------------------- >> .../log4j/perf/nogc/OpenHashMapContextData.java | 85 +++++++++++++++----- >> 1 file changed, 67 insertions(+), 18 deletions(-) >> ---------------------------------------------------------------------- >> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7615afad/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashMapContextData.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashMapContextData.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashMapContextData.java >> index 26bdf53..a7357b8 100644 >> --- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashMapContextData.java >> +++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashMapContextData.java >> @@ -67,6 +67,7 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> /** The default load factor of a hash table. */ >> public static final float DEFAULT_LOAD_FACTOR = .75f; >> >> + private static final String FROZEN = "Frozen collection cannot be modified"; >> private static final long serialVersionUID = -1486744623338827187L; >> >> /** The array of keys. */ >> @@ -89,6 +90,8 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> protected final float loadFactor; >> >> private V defRetValue = null; >> + private boolean immutable; >> + private transient boolean iterating; >> >> /** >> * Creates a new hash map with initial expected >> @@ -193,6 +196,18 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> } >> }; >> >> + private void assertNotFrozen() { >> + if (immutable) { >> + throw new UnsupportedOperationException(FROZEN); >> + } >> + } >> + >> + private void assertNoConcurrentModification() { >> + if (iterating) { >> + throw new ConcurrentModificationException(); >> + } >> + } >> + >> @SuppressWarnings("unchecked") >> private void initFrom0(final OpenHashMapContextData other) { >> // this.loadFactor = other.loadFactor; // final field >> @@ -250,6 +265,9 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> if (size == 0) { >> return; >> } >> + assertNotFrozen(); >> + assertNoConcurrentModification(); >> + >> size = 0; >> containsNullKey = false; >> Arrays.fill(keys, (null)); >> @@ -323,20 +341,26 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> final int startSize = size; >> final K myKeys[] = this.keys; >> int pos = arraySize; >> - if (containsNullKey) { >> - action.accept((String) myKeys[pos], (VAL) values[pos]); >> - if (size != startSize) { >> - throw new ConcurrentModificationException(); >> - } >> - } >> - --pos; >> - for (; pos >= 0; pos--) { >> - if (myKeys[pos] != null) { >> + >> + iterating = true; >> + try { >> + if (containsNullKey) { >> action.accept((String) myKeys[pos], (VAL) values[pos]); >> if (size != startSize) { >> throw new ConcurrentModificationException(); >> } >> } >> + --pos; >> + for (; pos >= 0; pos--) { >> + if (myKeys[pos] != null) { >> + action.accept((String) myKeys[pos], (VAL) values[pos]); >> + if (size != startSize) { >> + throw new ConcurrentModificationException(); >> + } >> + } >> + } >> + } finally { >> + iterating = false; >> } >> } >> >> @@ -346,20 +370,26 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> final int startSize = size; >> final K myKeys[] = this.keys; >> int pos = arraySize; >> - if (containsNullKey) { >> - action.accept((String) myKeys[pos], (VAL) values[pos], state); >> - if (size != startSize) { >> - throw new ConcurrentModificationException(); >> - } >> - } >> - --pos; >> - for (; pos >= 0; pos--) { >> - if (myKeys[pos] != null) { >> + >> + iterating = true; >> + try { >> + if (containsNullKey) { >> action.accept((String) myKeys[pos], (VAL) values[pos], state); >> if (size != startSize) { >> throw new ConcurrentModificationException(); >> } >> } >> + --pos; >> + for (; pos >= 0; pos--) { >> + if (myKeys[pos] != null) { >> + action.accept((String) myKeys[pos], (VAL) values[pos], state); >> + if (size != startSize) { >> + throw new ConcurrentModificationException(); >> + } >> + } >> + } >> + } finally { >> + iterating = false; >> } >> } >> >> @@ -453,6 +483,9 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> >> @Override >> public void putAll(final ContextData source) { >> + assertNotFrozen(); >> + assertNoConcurrentModification(); >> + >> if (size() == 0 && source instanceof OpenHashMapContextData) { >> initFrom0((OpenHashMapContextData) source); >> } else if (source != null) { >> @@ -475,6 +508,9 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> } >> >> private V putObjectValue(final K k, final V v) { >> + assertNotFrozen(); >> + assertNoConcurrentModification(); >> + >> final int pos = insert(k, v); >> if (pos < 0) { >> return defRetValue; >> @@ -495,8 +531,21 @@ public class OpenHashMapContextData<K, V> implements MutableContextData, ThreadC >> removeObjectKey((Object) key); >> } >> >> + @Override >> + public void freeze() { >> + immutable = true; >> + } >> + >> + @Override >> + public boolean isFrozen() { >> + return immutable; >> + } >> + >> @SuppressWarnings("unchecked") >> private V removeObjectKey(final Object k) { >> + assertNotFrozen(); >> + assertNoConcurrentModification(); >> + >> if (k == null) { >> if (containsNullKey) { >> return removeNullEntry(); >>