diff options
Diffstat (limited to 'guava/src/com/google/common/collect/Synchronized.java')
-rw-r--r-- | guava/src/com/google/common/collect/Synchronized.java | 1565 |
1 files changed, 1565 insertions, 0 deletions
diff --git a/guava/src/com/google/common/collect/Synchronized.java b/guava/src/com/google/common/collect/Synchronized.java new file mode 100644 index 0000000..4262b27 --- /dev/null +++ b/guava/src/com/google/common/collect/Synchronized.java @@ -0,0 +1,1565 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; + +import javax.annotation.Nullable; + +/** + * Synchronized collection views. The returned synchronized collection views are + * serializable if the backing collection and the mutex are serializable. + * + * <p>If {@code null} is passed as the {@code mutex} parameter to any of this + * class's top-level methods or inner class constructors, the created object + * uses itself as the synchronization mutex. + * + * <p>This class should be used by other collection classes only. + * + * @author Mike Bostock + * @author Jared Levy + */ +@GwtCompatible(emulated = true) +final class Synchronized { + private Synchronized() {} + + static class SynchronizedObject implements Serializable { + final Object delegate; + final Object mutex; + + SynchronizedObject(Object delegate, @Nullable Object mutex) { + this.delegate = checkNotNull(delegate); + this.mutex = (mutex == null) ? this : mutex; + } + + Object delegate() { + return delegate; + } + + // No equals and hashCode; see ForwardingObject for details. + + @Override public String toString() { + synchronized (mutex) { + return delegate.toString(); + } + } + + // Serialization invokes writeObject only when it's private. + // The SynchronizedObject subclasses don't need a writeObject method since + // they don't contain any non-transient member variables, while the + // following writeObject() handles the SynchronizedObject members. + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + synchronized (mutex) { + stream.defaultWriteObject(); + } + } + + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0; + } + + private static <E> Collection<E> collection( + Collection<E> collection, @Nullable Object mutex) { + return new SynchronizedCollection<E>(collection, mutex); + } + + @VisibleForTesting static class SynchronizedCollection<E> + extends SynchronizedObject implements Collection<E> { + private SynchronizedCollection( + Collection<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @SuppressWarnings("unchecked") + @Override Collection<E> delegate() { + return (Collection<E>) super.delegate(); + } + + @Override + public boolean add(E e) { + synchronized (mutex) { + return delegate().add(e); + } + } + + @Override + public boolean addAll(Collection<? extends E> c) { + synchronized (mutex) { + return delegate().addAll(c); + } + } + + @Override + public void clear() { + synchronized (mutex) { + delegate().clear(); + } + } + + @Override + public boolean contains(Object o) { + synchronized (mutex) { + return delegate().contains(o); + } + } + + @Override + public boolean containsAll(Collection<?> c) { + synchronized (mutex) { + return delegate().containsAll(c); + } + } + + @Override + public boolean isEmpty() { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + @Override + public Iterator<E> iterator() { + return delegate().iterator(); // manually synchronized + } + + @Override + public boolean remove(Object o) { + synchronized (mutex) { + return delegate().remove(o); + } + } + + @Override + public boolean removeAll(Collection<?> c) { + synchronized (mutex) { + return delegate().removeAll(c); + } + } + + @Override + public boolean retainAll(Collection<?> c) { + synchronized (mutex) { + return delegate().retainAll(c); + } + } + + @Override + public int size() { + synchronized (mutex) { + return delegate().size(); + } + } + + @Override + public Object[] toArray() { + synchronized (mutex) { + return delegate().toArray(); + } + } + + @Override + public <T> T[] toArray(T[] a) { + synchronized (mutex) { + return delegate().toArray(a); + } + } + + private static final long serialVersionUID = 0; + } + + @VisibleForTesting static <E> Set<E> set(Set<E> set, @Nullable Object mutex) { + return new SynchronizedSet<E>(set, mutex); + } + + static class SynchronizedSet<E> + extends SynchronizedCollection<E> implements Set<E> { + + SynchronizedSet(Set<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override Set<E> delegate() { + return (Set<E>) super.delegate(); + } + + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + private static final long serialVersionUID = 0; + } + + private static <E> SortedSet<E> sortedSet( + SortedSet<E> set, @Nullable Object mutex) { + return new SynchronizedSortedSet<E>(set, mutex); + } + + static class SynchronizedSortedSet<E> extends SynchronizedSet<E> + implements SortedSet<E> { + SynchronizedSortedSet(SortedSet<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override SortedSet<E> delegate() { + return (SortedSet<E>) super.delegate(); + } + + @Override + public Comparator<? super E> comparator() { + synchronized (mutex) { + return delegate().comparator(); + } + } + + @Override + public SortedSet<E> subSet(E fromElement, E toElement) { + synchronized (mutex) { + return sortedSet(delegate().subSet(fromElement, toElement), mutex); + } + } + + @Override + public SortedSet<E> headSet(E toElement) { + synchronized (mutex) { + return sortedSet(delegate().headSet(toElement), mutex); + } + } + + @Override + public SortedSet<E> tailSet(E fromElement) { + synchronized (mutex) { + return sortedSet(delegate().tailSet(fromElement), mutex); + } + } + + @Override + public E first() { + synchronized (mutex) { + return delegate().first(); + } + } + + @Override + public E last() { + synchronized (mutex) { + return delegate().last(); + } + } + + private static final long serialVersionUID = 0; + } + + private static <E> List<E> list(List<E> list, @Nullable Object mutex) { + return (list instanceof RandomAccess) + ? new SynchronizedRandomAccessList<E>(list, mutex) + : new SynchronizedList<E>(list, mutex); + } + + private static class SynchronizedList<E> extends SynchronizedCollection<E> + implements List<E> { + SynchronizedList(List<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override List<E> delegate() { + return (List<E>) super.delegate(); + } + + @Override + public void add(int index, E element) { + synchronized (mutex) { + delegate().add(index, element); + } + } + + @Override + public boolean addAll(int index, Collection<? extends E> c) { + synchronized (mutex) { + return delegate().addAll(index, c); + } + } + + @Override + public E get(int index) { + synchronized (mutex) { + return delegate().get(index); + } + } + + @Override + public int indexOf(Object o) { + synchronized (mutex) { + return delegate().indexOf(o); + } + } + + @Override + public int lastIndexOf(Object o) { + synchronized (mutex) { + return delegate().lastIndexOf(o); + } + } + + @Override + public ListIterator<E> listIterator() { + return delegate().listIterator(); // manually synchronized + } + + @Override + public ListIterator<E> listIterator(int index) { + return delegate().listIterator(index); // manually synchronized + } + + @Override + public E remove(int index) { + synchronized (mutex) { + return delegate().remove(index); + } + } + + @Override + public E set(int index, E element) { + synchronized (mutex) { + return delegate().set(index, element); + } + } + + @Override + public List<E> subList(int fromIndex, int toIndex) { + synchronized (mutex) { + return list(delegate().subList(fromIndex, toIndex), mutex); + } + } + + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + private static final long serialVersionUID = 0; + } + + private static class SynchronizedRandomAccessList<E> + extends SynchronizedList<E> implements RandomAccess { + SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) { + super(list, mutex); + } + private static final long serialVersionUID = 0; + } + + static <E> Multiset<E> multiset( + Multiset<E> multiset, @Nullable Object mutex) { + if (multiset instanceof SynchronizedMultiset || + multiset instanceof ImmutableMultiset) { + return multiset; + } + return new SynchronizedMultiset<E>(multiset, mutex); + } + + private static class SynchronizedMultiset<E> extends SynchronizedCollection<E> + implements Multiset<E> { + transient Set<E> elementSet; + transient Set<Entry<E>> entrySet; + + SynchronizedMultiset(Multiset<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override Multiset<E> delegate() { + return (Multiset<E>) super.delegate(); + } + + @Override + public int count(Object o) { + synchronized (mutex) { + return delegate().count(o); + } + } + + @Override + public int add(E e, int n) { + synchronized (mutex) { + return delegate().add(e, n); + } + } + + @Override + public int remove(Object o, int n) { + synchronized (mutex) { + return delegate().remove(o, n); + } + } + + @Override + public int setCount(E element, int count) { + synchronized (mutex) { + return delegate().setCount(element, count); + } + } + + @Override + public boolean setCount(E element, int oldCount, int newCount) { + synchronized (mutex) { + return delegate().setCount(element, oldCount, newCount); + } + } + + @Override + public Set<E> elementSet() { + synchronized (mutex) { + if (elementSet == null) { + elementSet = typePreservingSet(delegate().elementSet(), mutex); + } + return elementSet; + } + } + + @Override + public Set<Entry<E>> entrySet() { + synchronized (mutex) { + if (entrySet == null) { + entrySet = typePreservingSet(delegate().entrySet(), mutex); + } + return entrySet; + } + } + + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + private static final long serialVersionUID = 0; + } + + static <K, V> Multimap<K, V> multimap( + Multimap<K, V> multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedMultimap || + multimap instanceof ImmutableMultimap) { + return multimap; + } + return new SynchronizedMultimap<K, V>(multimap, mutex); + } + + private static class SynchronizedMultimap<K, V> extends SynchronizedObject + implements Multimap<K, V> { + transient Set<K> keySet; + transient Collection<V> valuesCollection; + transient Collection<Map.Entry<K, V>> entries; + transient Map<K, Collection<V>> asMap; + transient Multiset<K> keys; + + @SuppressWarnings("unchecked") + @Override Multimap<K, V> delegate() { + return (Multimap<K, V>) super.delegate(); + } + + SynchronizedMultimap(Multimap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override + public int size() { + synchronized (mutex) { + return delegate().size(); + } + } + + @Override + public boolean isEmpty() { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + @Override + public boolean containsKey(Object key) { + synchronized (mutex) { + return delegate().containsKey(key); + } + } + + @Override + public boolean containsValue(Object value) { + synchronized (mutex) { + return delegate().containsValue(value); + } + } + + @Override + public boolean containsEntry(Object key, Object value) { + synchronized (mutex) { + return delegate().containsEntry(key, value); + } + } + + @Override + public Collection<V> get(K key) { + synchronized (mutex) { + return typePreservingCollection(delegate().get(key), mutex); + } + } + + @Override + public boolean put(K key, V value) { + synchronized (mutex) { + return delegate().put(key, value); + } + } + + @Override + public boolean putAll(K key, Iterable<? extends V> values) { + synchronized (mutex) { + return delegate().putAll(key, values); + } + } + + @Override + public boolean putAll(Multimap<? extends K, ? extends V> multimap) { + synchronized (mutex) { + return delegate().putAll(multimap); + } + } + + @Override + public Collection<V> replaceValues(K key, Iterable<? extends V> values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); // copy not synchronized + } + } + + @Override + public boolean remove(Object key, Object value) { + synchronized (mutex) { + return delegate().remove(key, value); + } + } + + @Override + public Collection<V> removeAll(Object key) { + synchronized (mutex) { + return delegate().removeAll(key); // copy not synchronized + } + } + + @Override + public void clear() { + synchronized (mutex) { + delegate().clear(); + } + } + + @Override + public Set<K> keySet() { + synchronized (mutex) { + if (keySet == null) { + keySet = typePreservingSet(delegate().keySet(), mutex); + } + return keySet; + } + } + + @Override + public Collection<V> values() { + synchronized (mutex) { + if (valuesCollection == null) { + valuesCollection = collection(delegate().values(), mutex); + } + return valuesCollection; + } + } + + @Override + public Collection<Map.Entry<K, V>> entries() { + synchronized (mutex) { + if (entries == null) { + entries = typePreservingCollection(delegate().entries(), mutex); + } + return entries; + } + } + + @Override + public Map<K, Collection<V>> asMap() { + synchronized (mutex) { + if (asMap == null) { + asMap = new SynchronizedAsMap<K, V>(delegate().asMap(), mutex); + } + return asMap; + } + } + + @Override + public Multiset<K> keys() { + synchronized (mutex) { + if (keys == null) { + keys = multiset(delegate().keys(), mutex); + } + return keys; + } + } + + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + private static final long serialVersionUID = 0; + } + + static <K, V> ListMultimap<K, V> listMultimap( + ListMultimap<K, V> multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedListMultimap || + multimap instanceof ImmutableListMultimap) { + return multimap; + } + return new SynchronizedListMultimap<K, V>(multimap, mutex); + } + + private static class SynchronizedListMultimap<K, V> + extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> { + SynchronizedListMultimap( + ListMultimap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + @Override ListMultimap<K, V> delegate() { + return (ListMultimap<K, V>) super.delegate(); + } + @Override public List<V> get(K key) { + synchronized (mutex) { + return list(delegate().get(key), mutex); + } + } + @Override public List<V> removeAll(Object key) { + synchronized (mutex) { + return delegate().removeAll(key); // copy not synchronized + } + } + @Override public List<V> replaceValues( + K key, Iterable<? extends V> values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); // copy not synchronized + } + } + private static final long serialVersionUID = 0; + } + + static <K, V> SetMultimap<K, V> setMultimap( + SetMultimap<K, V> multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedSetMultimap || + multimap instanceof ImmutableSetMultimap) { + return multimap; + } + return new SynchronizedSetMultimap<K, V>(multimap, mutex); + } + + private static class SynchronizedSetMultimap<K, V> + extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> { + transient Set<Map.Entry<K, V>> entrySet; + + SynchronizedSetMultimap( + SetMultimap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + @Override SetMultimap<K, V> delegate() { + return (SetMultimap<K, V>) super.delegate(); + } + @Override public Set<V> get(K key) { + synchronized (mutex) { + return set(delegate().get(key), mutex); + } + } + @Override public Set<V> removeAll(Object key) { + synchronized (mutex) { + return delegate().removeAll(key); // copy not synchronized + } + } + @Override public Set<V> replaceValues( + K key, Iterable<? extends V> values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); // copy not synchronized + } + } + @Override public Set<Map.Entry<K, V>> entries() { + synchronized (mutex) { + if (entrySet == null) { + entrySet = set(delegate().entries(), mutex); + } + return entrySet; + } + } + private static final long serialVersionUID = 0; + } + + static <K, V> SortedSetMultimap<K, V> sortedSetMultimap( + SortedSetMultimap<K, V> multimap, @Nullable Object mutex) { + if (multimap instanceof SynchronizedSortedSetMultimap) { + return multimap; + } + return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex); + } + + private static class SynchronizedSortedSetMultimap<K, V> + extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> { + SynchronizedSortedSetMultimap( + SortedSetMultimap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + @Override SortedSetMultimap<K, V> delegate() { + return (SortedSetMultimap<K, V>) super.delegate(); + } + @Override public SortedSet<V> get(K key) { + synchronized (mutex) { + return sortedSet(delegate().get(key), mutex); + } + } + @Override public SortedSet<V> removeAll(Object key) { + synchronized (mutex) { + return delegate().removeAll(key); // copy not synchronized + } + } + @Override public SortedSet<V> replaceValues( + K key, Iterable<? extends V> values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); // copy not synchronized + } + } + @Override + public Comparator<? super V> valueComparator() { + synchronized (mutex) { + return delegate().valueComparator(); + } + } + private static final long serialVersionUID = 0; + } + + private static <E> Collection<E> typePreservingCollection( + Collection<E> collection, @Nullable Object mutex) { + if (collection instanceof SortedSet) { + return sortedSet((SortedSet<E>) collection, mutex); + } + if (collection instanceof Set) { + return set((Set<E>) collection, mutex); + } + if (collection instanceof List) { + return list((List<E>) collection, mutex); + } + return collection(collection, mutex); + } + + private static <E> Set<E> typePreservingSet( + Set<E> set, @Nullable Object mutex) { + if (set instanceof SortedSet) { + return sortedSet((SortedSet<E>) set, mutex); + } else { + return set(set, mutex); + } + } + + private static class SynchronizedAsMapEntries<K, V> + extends SynchronizedSet<Map.Entry<K, Collection<V>>> { + SynchronizedAsMapEntries( + Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() { + // Must be manually synchronized. + final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator(); + return new ForwardingIterator<Map.Entry<K, Collection<V>>>() { + @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() { + return iterator; + } + + @Override public Map.Entry<K, Collection<V>> next() { + final Map.Entry<K, Collection<V>> entry = super.next(); + return new ForwardingMapEntry<K, Collection<V>>() { + @Override protected Map.Entry<K, Collection<V>> delegate() { + return entry; + } + @Override public Collection<V> getValue() { + return typePreservingCollection(entry.getValue(), mutex); + } + }; + } + }; + } + + // See Collections.CheckedMap.CheckedEntrySet for details on attacks. + + @Override public Object[] toArray() { + synchronized (mutex) { + return ObjectArrays.toArrayImpl(delegate()); + } + } + @Override public <T> T[] toArray(T[] array) { + synchronized (mutex) { + return ObjectArrays.toArrayImpl(delegate(), array); + } + } + @Override public boolean contains(Object o) { + synchronized (mutex) { + return Maps.containsEntryImpl(delegate(), o); + } + } + @Override public boolean containsAll(Collection<?> c) { + synchronized (mutex) { + return Collections2.containsAllImpl(delegate(), c); + } + } + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return Sets.equalsImpl(delegate(), o); + } + } + @Override public boolean remove(Object o) { + synchronized (mutex) { + return Maps.removeEntryImpl(delegate(), o); + } + } + @Override public boolean removeAll(Collection<?> c) { + synchronized (mutex) { + return Iterators.removeAll(delegate().iterator(), c); + } + } + @Override public boolean retainAll(Collection<?> c) { + synchronized (mutex) { + return Iterators.retainAll(delegate().iterator(), c); + } + } + + private static final long serialVersionUID = 0; + } + + @VisibleForTesting + static <K, V> Map<K, V> map(Map<K, V> map, @Nullable Object mutex) { + return new SynchronizedMap<K, V>(map, mutex); + } + + private static class SynchronizedMap<K, V> extends SynchronizedObject + implements Map<K, V> { + transient Set<K> keySet; + transient Collection<V> values; + transient Set<Map.Entry<K, V>> entrySet; + + SynchronizedMap(Map<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @SuppressWarnings("unchecked") + @Override Map<K, V> delegate() { + return (Map<K, V>) super.delegate(); + } + + @Override + public void clear() { + synchronized (mutex) { + delegate().clear(); + } + } + + @Override + public boolean containsKey(Object key) { + synchronized (mutex) { + return delegate().containsKey(key); + } + } + + @Override + public boolean containsValue(Object value) { + synchronized (mutex) { + return delegate().containsValue(value); + } + } + + @Override + public Set<Map.Entry<K, V>> entrySet() { + synchronized (mutex) { + if (entrySet == null) { + entrySet = set(delegate().entrySet(), mutex); + } + return entrySet; + } + } + + @Override + public V get(Object key) { + synchronized (mutex) { + return delegate().get(key); + } + } + + @Override + public boolean isEmpty() { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + @Override + public Set<K> keySet() { + synchronized (mutex) { + if (keySet == null) { + keySet = set(delegate().keySet(), mutex); + } + return keySet; + } + } + + @Override + public V put(K key, V value) { + synchronized (mutex) { + return delegate().put(key, value); + } + } + + @Override + public void putAll(Map<? extends K, ? extends V> map) { + synchronized (mutex) { + delegate().putAll(map); + } + } + + @Override + public V remove(Object key) { + synchronized (mutex) { + return delegate().remove(key); + } + } + + @Override + public int size() { + synchronized (mutex) { + return delegate().size(); + } + } + + @Override + public Collection<V> values() { + synchronized (mutex) { + if (values == null) { + values = collection(delegate().values(), mutex); + } + return values; + } + } + + @Override public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + private static final long serialVersionUID = 0; + } + + static <K, V> SortedMap<K, V> sortedMap( + SortedMap<K, V> sortedMap, @Nullable Object mutex) { + return new SynchronizedSortedMap<K, V>(sortedMap, mutex); + } + + static class SynchronizedSortedMap<K, V> extends SynchronizedMap<K, V> + implements SortedMap<K, V> { + + SynchronizedSortedMap(SortedMap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override SortedMap<K, V> delegate() { + return (SortedMap<K, V>) super.delegate(); + } + + @Override public Comparator<? super K> comparator() { + synchronized (mutex) { + return delegate().comparator(); + } + } + + @Override public K firstKey() { + synchronized (mutex) { + return delegate().firstKey(); + } + } + + @Override public SortedMap<K, V> headMap(K toKey) { + synchronized (mutex) { + return sortedMap(delegate().headMap(toKey), mutex); + } + } + + @Override public K lastKey() { + synchronized (mutex) { + return delegate().lastKey(); + } + } + + @Override public SortedMap<K, V> subMap(K fromKey, K toKey) { + synchronized (mutex) { + return sortedMap(delegate().subMap(fromKey, toKey), mutex); + } + } + + @Override public SortedMap<K, V> tailMap(K fromKey) { + synchronized (mutex) { + return sortedMap(delegate().tailMap(fromKey), mutex); + } + } + + private static final long serialVersionUID = 0; + } + + static <K, V> BiMap<K, V> biMap(BiMap<K, V> bimap, @Nullable Object mutex) { + if (bimap instanceof SynchronizedBiMap || + bimap instanceof ImmutableBiMap) { + return bimap; + } + return new SynchronizedBiMap<K, V>(bimap, mutex, null); + } + + @VisibleForTesting static class SynchronizedBiMap<K, V> + extends SynchronizedMap<K, V> implements BiMap<K, V>, Serializable { + private transient Set<V> valueSet; + private transient BiMap<V, K> inverse; + + private SynchronizedBiMap(BiMap<K, V> delegate, @Nullable Object mutex, + @Nullable BiMap<V, K> inverse) { + super(delegate, mutex); + this.inverse = inverse; + } + + @Override BiMap<K, V> delegate() { + return (BiMap<K, V>) super.delegate(); + } + + @Override public Set<V> values() { + synchronized (mutex) { + if (valueSet == null) { + valueSet = set(delegate().values(), mutex); + } + return valueSet; + } + } + + @Override + public V forcePut(K key, V value) { + synchronized (mutex) { + return delegate().forcePut(key, value); + } + } + + @Override + public BiMap<V, K> inverse() { + synchronized (mutex) { + if (inverse == null) { + inverse + = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this); + } + return inverse; + } + } + + private static final long serialVersionUID = 0; + } + + private static class SynchronizedAsMap<K, V> + extends SynchronizedMap<K, Collection<V>> { + transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet; + transient Collection<Collection<V>> asMapValues; + + SynchronizedAsMap(Map<K, Collection<V>> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override public Collection<V> get(Object key) { + synchronized (mutex) { + Collection<V> collection = super.get(key); + return (collection == null) ? null + : typePreservingCollection(collection, mutex); + } + } + + @Override public Set<Map.Entry<K, Collection<V>>> entrySet() { + synchronized (mutex) { + if (asMapEntrySet == null) { + asMapEntrySet = new SynchronizedAsMapEntries<K, V>( + delegate().entrySet(), mutex); + } + return asMapEntrySet; + } + } + + @Override public Collection<Collection<V>> values() { + synchronized (mutex) { + if (asMapValues == null) { + asMapValues + = new SynchronizedAsMapValues<V>(delegate().values(), mutex); + } + return asMapValues; + } + } + + @Override public boolean containsValue(Object o) { + // values() and its contains() method are both synchronized. + return values().contains(o); + } + + private static final long serialVersionUID = 0; + } + + private static class SynchronizedAsMapValues<V> + extends SynchronizedCollection<Collection<V>> { + SynchronizedAsMapValues( + Collection<Collection<V>> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override public Iterator<Collection<V>> iterator() { + // Must be manually synchronized. + final Iterator<Collection<V>> iterator = super.iterator(); + return new ForwardingIterator<Collection<V>>() { + @Override protected Iterator<Collection<V>> delegate() { + return iterator; + } + @Override public Collection<V> next() { + return typePreservingCollection(super.next(), mutex); + } + }; + } + + private static final long serialVersionUID = 0; + } + + @GwtIncompatible("NavigableSet") + @VisibleForTesting + static class SynchronizedNavigableSet<E> extends SynchronizedSortedSet<E> + implements NavigableSet<E> { + SynchronizedNavigableSet(NavigableSet<E> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override NavigableSet<E> delegate() { + return (NavigableSet<E>) super.delegate(); + } + + @Override public E ceiling(E e) { + synchronized (mutex) { + return delegate().ceiling(e); + } + } + + @Override public Iterator<E> descendingIterator() { + return delegate().descendingIterator(); // manually synchronized + } + + transient NavigableSet<E> descendingSet; + + @Override public NavigableSet<E> descendingSet() { + synchronized (mutex) { + if (descendingSet == null) { + NavigableSet<E> dS = + Synchronized.navigableSet(delegate().descendingSet(), mutex); + descendingSet = dS; + return dS; + } + return descendingSet; + } + } + + @Override public E floor(E e) { + synchronized (mutex) { + return delegate().floor(e); + } + } + + @Override public NavigableSet<E> headSet(E toElement, boolean inclusive) { + synchronized (mutex) { + return Synchronized.navigableSet( + delegate().headSet(toElement, inclusive), mutex); + } + } + + @Override public E higher(E e) { + synchronized (mutex) { + return delegate().higher(e); + } + } + + @Override public E lower(E e) { + synchronized (mutex) { + return delegate().lower(e); + } + } + + @Override public E pollFirst() { + synchronized (mutex) { + return delegate().pollFirst(); + } + } + + @Override public E pollLast() { + synchronized (mutex) { + return delegate().pollLast(); + } + } + + @Override public NavigableSet<E> subSet(E fromElement, + boolean fromInclusive, E toElement, boolean toInclusive) { + synchronized (mutex) { + return Synchronized.navigableSet(delegate().subSet( + fromElement, fromInclusive, toElement, toInclusive), mutex); + } + } + + @Override public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { + synchronized (mutex) { + return Synchronized.navigableSet( + delegate().tailSet(fromElement, inclusive), mutex); + } + } + + @Override public SortedSet<E> headSet(E toElement) { + return headSet(toElement, false); + } + + @Override public SortedSet<E> subSet(E fromElement, E toElement) { + return subSet(fromElement, true, toElement, false); + } + + @Override public SortedSet<E> tailSet(E fromElement) { + return tailSet(fromElement, true); + } + + private static final long serialVersionUID = 0; + } + + @GwtIncompatible("NavigableSet") + static <E> NavigableSet<E> navigableSet( + NavigableSet<E> navigableSet, @Nullable Object mutex) { + return new SynchronizedNavigableSet<E>(navigableSet, mutex); + } + + @GwtIncompatible("NavigableSet") + static <E> NavigableSet<E> navigableSet(NavigableSet<E> navigableSet) { + return navigableSet(navigableSet, null); + } + + @GwtIncompatible("NavigableMap") + static <K, V> NavigableMap<K, V> navigableMap( + NavigableMap<K, V> navigableMap) { + return navigableMap(navigableMap, null); + } + + @GwtIncompatible("NavigableMap") + static <K, V> NavigableMap<K, V> navigableMap( + NavigableMap<K, V> navigableMap, @Nullable Object mutex) { + return new SynchronizedNavigableMap<K, V>(navigableMap, mutex); + } + + @GwtIncompatible("NavigableMap") + @VisibleForTesting static class SynchronizedNavigableMap<K, V> + extends SynchronizedSortedMap<K, V> implements NavigableMap<K, V> { + + SynchronizedNavigableMap( + NavigableMap<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @Override NavigableMap<K, V> delegate() { + return (NavigableMap<K, V>) super.delegate(); + } + + @Override public Entry<K, V> ceilingEntry(K key) { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().ceilingEntry(key), mutex); + } + } + + @Override public K ceilingKey(K key) { + synchronized (mutex) { + return delegate().ceilingKey(key); + } + } + + transient NavigableSet<K> descendingKeySet; + + @Override public NavigableSet<K> descendingKeySet() { + synchronized (mutex) { + if (descendingKeySet == null) { + return descendingKeySet = + Synchronized.navigableSet(delegate().descendingKeySet(), mutex); + } + return descendingKeySet; + } + } + + transient NavigableMap<K, V> descendingMap; + + @Override public NavigableMap<K, V> descendingMap() { + synchronized (mutex) { + if (descendingMap == null) { + return descendingMap = + navigableMap(delegate().descendingMap(), mutex); + } + return descendingMap; + } + } + + @Override public Entry<K, V> firstEntry() { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().firstEntry(), mutex); + } + } + + @Override public Entry<K, V> floorEntry(K key) { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().floorEntry(key), mutex); + } + } + + @Override public K floorKey(K key) { + synchronized (mutex) { + return delegate().floorKey(key); + } + } + + @Override public NavigableMap<K, V> headMap(K toKey, boolean inclusive) { + synchronized (mutex) { + return navigableMap( + delegate().headMap(toKey, inclusive), mutex); + } + } + + @Override public Entry<K, V> higherEntry(K key) { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().higherEntry(key), mutex); + } + } + + @Override public K higherKey(K key) { + synchronized (mutex) { + return delegate().higherKey(key); + } + } + + @Override public Entry<K, V> lastEntry() { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().lastEntry(), mutex); + } + } + + @Override public Entry<K, V> lowerEntry(K key) { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().lowerEntry(key), mutex); + } + } + + @Override public K lowerKey(K key) { + synchronized (mutex) { + return delegate().lowerKey(key); + } + } + + @Override public Set<K> keySet() { + return navigableKeySet(); + } + + transient NavigableSet<K> navigableKeySet; + + @Override public NavigableSet<K> navigableKeySet() { + synchronized (mutex) { + if (navigableKeySet == null) { + return navigableKeySet = + Synchronized.navigableSet(delegate().navigableKeySet(), mutex); + } + return navigableKeySet; + } + } + + @Override public Entry<K, V> pollFirstEntry() { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().pollFirstEntry(), mutex); + } + } + + @Override public Entry<K, V> pollLastEntry() { + synchronized (mutex) { + return nullableSynchronizedEntry(delegate().pollLastEntry(), mutex); + } + } + + @Override public NavigableMap<K, V> subMap( + K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + synchronized (mutex) { + return navigableMap( + delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), + mutex); + } + } + + @Override public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) { + synchronized (mutex) { + return navigableMap( + delegate().tailMap(fromKey, inclusive), mutex); + } + } + + @Override public SortedMap<K, V> headMap(K toKey) { + return headMap(toKey, false); + } + + @Override public SortedMap<K, V> subMap(K fromKey, K toKey) { + return subMap(fromKey, true, toKey, false); + } + + @Override public SortedMap<K, V> tailMap(K fromKey) { + return tailMap(fromKey, true); + } + + private static final long serialVersionUID = 0; + } + + @GwtIncompatible("works but is needed only for NavigableMap") + private static <K, V> Entry<K, V> nullableSynchronizedEntry( + @Nullable Entry<K, V> entry, @Nullable Object mutex) { + if (entry == null) { + return null; + } + return new SynchronizedEntry<K, V>(entry, mutex); + } + + @GwtIncompatible("works but is needed only for NavigableMap") + private static class SynchronizedEntry<K, V> extends SynchronizedObject + implements Entry<K, V> { + + SynchronizedEntry(Entry<K, V> delegate, @Nullable Object mutex) { + super(delegate, mutex); + } + + @SuppressWarnings("unchecked") // guaranteed by the constructor + @Override Entry<K, V> delegate() { + return (Entry<K, V>) super.delegate(); + } + + @Override public boolean equals(Object obj) { + synchronized (mutex) { + return delegate().equals(obj); + } + } + + @Override public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + @Override public K getKey() { + synchronized (mutex) { + return delegate().getKey(); + } + } + + @Override public V getValue() { + synchronized (mutex) { + return delegate().getValue(); + } + } + + @Override public V setValue(V value) { + synchronized (mutex) { + return delegate().setValue(value); + } + } + + private static final long serialVersionUID = 0; + } +} |