summaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/Synchronized.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/Synchronized.java')
-rw-r--r--guava/src/com/google/common/collect/Synchronized.java1565
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;
+ }
+}