I Googled if there was any established terminology for turning a mutable object into an immutable one and "freeze" came up multiple times.
On Sun, Sep 4, 2016 at 11:48 PM, Gary Gregory <garydgreg...@gmail.com> wrote: > 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(); > >> >