All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.collect.Synchronized Maven / Gradle / Ivy

There is a newer version: 33.3.0-jre-r3
Show newest version
/*
 * 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.J2ktIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.j2objc.annotations.RetainedWith;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * Synchronized collection views. The returned synchronized collection views are serializable if the
 * backing collection and the mutex are serializable.
 *
 * 

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. * *

This class should be used by other collection classes only. * * @author Mike Bostock * @author Jared Levy */ @J2ktIncompatible @GwtCompatible(emulated = true) @ElementTypesAreNonnullByDefault /* * I have decided not to bother adding @ParametricNullness annotations in this class. Adding them is * a lot of busy work, and the annotation matters only when the APIs to be annotated are visible to * Kotlin code. In this class, nothing is publicly visible (nor exposed indirectly through a * publicly visible subclass), and I doubt any of our current or future Kotlin extensions for the * package will refer to the class. Plus, @ParametricNullness is only a temporary workaround, * anyway, so we just need to get by without the annotations here until Kotlin better understands * our other nullness annotations. */ final class Synchronized { private Synchronized() {} static class SynchronizedObject implements Serializable { final Object delegate; final Object mutex; SynchronizedObject(Object delegate, @CheckForNull 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 @J2ktIncompatible private void writeObject(ObjectOutputStream stream) throws IOException { synchronized (mutex) { stream.defaultWriteObject(); } } @GwtIncompatible // not needed in emulated source @J2ktIncompatible private static final long serialVersionUID = 0; } private static Collection collection( Collection collection, @CheckForNull Object mutex) { return new SynchronizedCollection<>(collection, mutex); } @VisibleForTesting static class SynchronizedCollection extends SynchronizedObject implements Collection { private SynchronizedCollection(Collection delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @SuppressWarnings("unchecked") @Override Collection delegate() { return (Collection) super.delegate(); } @Override public boolean add(E e) { synchronized (mutex) { return delegate().add(e); } } @Override public boolean addAll(Collection c) { synchronized (mutex) { return delegate().addAll(c); } } @Override public void clear() { synchronized (mutex) { delegate().clear(); } } @Override public boolean contains(@CheckForNull 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 iterator() { return delegate().iterator(); // manually synchronized } @Override public Spliterator spliterator() { synchronized (mutex) { return delegate().spliterator(); } } @Override public Stream stream() { synchronized (mutex) { return delegate().stream(); } } @Override public Stream parallelStream() { synchronized (mutex) { return delegate().parallelStream(); } } @Override public void forEach(Consumer action) { synchronized (mutex) { delegate().forEach(action); } } @Override public boolean remove(@CheckForNull 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 boolean removeIf(Predicate filter) { synchronized (mutex) { return delegate().removeIf(filter); } } @Override public int size() { synchronized (mutex) { return delegate().size(); } } @Override public @Nullable Object[] toArray() { synchronized (mutex) { return delegate().toArray(); } } @Override @SuppressWarnings("nullness") // b/192354773 in our checker affects toArray declarations public T[] toArray(T[] a) { synchronized (mutex) { return delegate().toArray(a); } } private static final long serialVersionUID = 0; } @VisibleForTesting static Set set(Set set, @CheckForNull Object mutex) { return new SynchronizedSet<>(set, mutex); } static class SynchronizedSet extends SynchronizedCollection implements Set { SynchronizedSet(Set delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override Set delegate() { return (Set) super.delegate(); } @Override public boolean equals(@CheckForNull 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 SortedSet sortedSet( SortedSet set, @CheckForNull Object mutex) { return new SynchronizedSortedSet<>(set, mutex); } static class SynchronizedSortedSet extends SynchronizedSet implements SortedSet { SynchronizedSortedSet(SortedSet delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override SortedSet delegate() { return (SortedSet) super.delegate(); } @Override @CheckForNull public Comparator comparator() { synchronized (mutex) { return delegate().comparator(); } } @Override public SortedSet subSet(E fromElement, E toElement) { synchronized (mutex) { return sortedSet(delegate().subSet(fromElement, toElement), mutex); } } @Override public SortedSet headSet(E toElement) { synchronized (mutex) { return sortedSet(delegate().headSet(toElement), mutex); } } @Override public SortedSet 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 List list( List list, @CheckForNull Object mutex) { return (list instanceof RandomAccess) ? new SynchronizedRandomAccessList(list, mutex) : new SynchronizedList(list, mutex); } static class SynchronizedList extends SynchronizedCollection implements List { SynchronizedList(List delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override List delegate() { return (List) super.delegate(); } @Override public void add(int index, E element) { synchronized (mutex) { delegate().add(index, element); } } @Override public boolean addAll(int index, Collection c) { synchronized (mutex) { return delegate().addAll(index, c); } } @Override public E get(int index) { synchronized (mutex) { return delegate().get(index); } } @Override public int indexOf(@CheckForNull Object o) { synchronized (mutex) { return delegate().indexOf(o); } } @Override public int lastIndexOf(@CheckForNull Object o) { synchronized (mutex) { return delegate().lastIndexOf(o); } } @Override public ListIterator listIterator() { return delegate().listIterator(); // manually synchronized } @Override public ListIterator 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 void replaceAll(UnaryOperator operator) { synchronized (mutex) { delegate().replaceAll(operator); } } @Override public void sort(@Nullable Comparator c) { synchronized (mutex) { delegate().sort(c); } } @Override public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return list(delegate().subList(fromIndex, toIndex), mutex); } } @Override public boolean equals(@CheckForNull 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 final class SynchronizedRandomAccessList extends SynchronizedList implements RandomAccess { SynchronizedRandomAccessList(List list, @CheckForNull Object mutex) { super(list, mutex); } private static final long serialVersionUID = 0; } static Multiset multiset( Multiset multiset, @CheckForNull Object mutex) { if (multiset instanceof SynchronizedMultiset || multiset instanceof ImmutableMultiset) { return multiset; } return new SynchronizedMultiset<>(multiset, mutex); } static final class SynchronizedMultiset extends SynchronizedCollection implements Multiset { @CheckForNull transient Set elementSet; @CheckForNull transient Set> entrySet; SynchronizedMultiset(Multiset delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override Multiset delegate() { return (Multiset) super.delegate(); } @Override public int count(@CheckForNull Object o) { synchronized (mutex) { return delegate().count(o); } } @Override public int add(@ParametricNullness E e, int n) { synchronized (mutex) { return delegate().add(e, n); } } @Override public int remove(@CheckForNull Object o, int n) { synchronized (mutex) { return delegate().remove(o, n); } } @Override public int setCount(@ParametricNullness E element, int count) { synchronized (mutex) { return delegate().setCount(element, count); } } @Override public boolean setCount(@ParametricNullness E element, int oldCount, int newCount) { synchronized (mutex) { return delegate().setCount(element, oldCount, newCount); } } @Override public Set elementSet() { synchronized (mutex) { if (elementSet == null) { elementSet = typePreservingSet(delegate().elementSet(), mutex); } return elementSet; } } @Override public Set> entrySet() { synchronized (mutex) { if (entrySet == null) { entrySet = typePreservingSet(delegate().entrySet(), mutex); } return entrySet; } } @Override public boolean equals(@CheckForNull 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 Multimap multimap( Multimap multimap, @CheckForNull Object mutex) { if (multimap instanceof SynchronizedMultimap || multimap instanceof BaseImmutableMultimap) { return multimap; } return new SynchronizedMultimap<>(multimap, mutex); } static class SynchronizedMultimap extends SynchronizedObject implements Multimap { @CheckForNull transient Set keySet; @CheckForNull transient Collection valuesCollection; @CheckForNull transient Collection> entries; @CheckForNull transient Map> asMap; @CheckForNull transient Multiset keys; @SuppressWarnings("unchecked") @Override Multimap delegate() { return (Multimap) super.delegate(); } SynchronizedMultimap(Multimap delegate, @CheckForNull 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(@CheckForNull Object key) { synchronized (mutex) { return delegate().containsKey(key); } } @Override public boolean containsValue(@CheckForNull Object value) { synchronized (mutex) { return delegate().containsValue(value); } } @Override public boolean containsEntry(@CheckForNull Object key, @CheckForNull Object value) { synchronized (mutex) { return delegate().containsEntry(key, value); } } @Override public Collection get(@ParametricNullness K key) { synchronized (mutex) { return typePreservingCollection(delegate().get(key), mutex); } } @Override public boolean put(@ParametricNullness K key, @ParametricNullness V value) { synchronized (mutex) { return delegate().put(key, value); } } @Override public boolean putAll(@ParametricNullness K key, Iterable values) { synchronized (mutex) { return delegate().putAll(key, values); } } @Override public boolean putAll(Multimap multimap) { synchronized (mutex) { return delegate().putAll(multimap); } } @Override public Collection replaceValues(@ParametricNullness K key, Iterable values) { synchronized (mutex) { return delegate().replaceValues(key, values); // copy not synchronized } } @Override public boolean remove(@CheckForNull Object key, @CheckForNull Object value) { synchronized (mutex) { return delegate().remove(key, value); } } @Override public Collection removeAll(@CheckForNull Object key) { synchronized (mutex) { return delegate().removeAll(key); // copy not synchronized } } @Override public void clear() { synchronized (mutex) { delegate().clear(); } } @Override public Set keySet() { synchronized (mutex) { if (keySet == null) { keySet = typePreservingSet(delegate().keySet(), mutex); } return keySet; } } @Override public Collection values() { synchronized (mutex) { if (valuesCollection == null) { valuesCollection = collection(delegate().values(), mutex); } return valuesCollection; } } @Override public Collection> entries() { synchronized (mutex) { if (entries == null) { entries = typePreservingCollection(delegate().entries(), mutex); } return entries; } } @Override public void forEach(BiConsumer action) { synchronized (mutex) { delegate().forEach(action); } } @Override public Map> asMap() { synchronized (mutex) { if (asMap == null) { asMap = new SynchronizedAsMap<>(delegate().asMap(), mutex); } return asMap; } } @Override public Multiset keys() { synchronized (mutex) { if (keys == null) { keys = multiset(delegate().keys(), mutex); } return keys; } } @Override public boolean equals(@CheckForNull 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 ListMultimap listMultimap( ListMultimap multimap, @CheckForNull Object mutex) { if (multimap instanceof SynchronizedListMultimap || multimap instanceof BaseImmutableMultimap) { return multimap; } return new SynchronizedListMultimap<>(multimap, mutex); } static final class SynchronizedListMultimap< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedMultimap implements ListMultimap { SynchronizedListMultimap(ListMultimap delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override ListMultimap delegate() { return (ListMultimap) super.delegate(); } @Override public List get(K key) { synchronized (mutex) { return list(delegate().get(key), mutex); } } @Override public List removeAll(@CheckForNull Object key) { synchronized (mutex) { return delegate().removeAll(key); // copy not synchronized } } @Override public List replaceValues(K key, Iterable values) { synchronized (mutex) { return delegate().replaceValues(key, values); // copy not synchronized } } private static final long serialVersionUID = 0; } static SetMultimap setMultimap( SetMultimap multimap, @CheckForNull Object mutex) { if (multimap instanceof SynchronizedSetMultimap || multimap instanceof BaseImmutableMultimap) { return multimap; } return new SynchronizedSetMultimap<>(multimap, mutex); } static class SynchronizedSetMultimap extends SynchronizedMultimap implements SetMultimap { @CheckForNull transient Set> entrySet; SynchronizedSetMultimap(SetMultimap delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override SetMultimap delegate() { return (SetMultimap) super.delegate(); } @Override public Set get(K key) { synchronized (mutex) { return set(delegate().get(key), mutex); } } @Override public Set removeAll(@CheckForNull Object key) { synchronized (mutex) { return delegate().removeAll(key); // copy not synchronized } } @Override public Set replaceValues(K key, Iterable values) { synchronized (mutex) { return delegate().replaceValues(key, values); // copy not synchronized } } @Override public Set> entries() { synchronized (mutex) { if (entrySet == null) { entrySet = set(delegate().entries(), mutex); } return entrySet; } } private static final long serialVersionUID = 0; } static SortedSetMultimap sortedSetMultimap( SortedSetMultimap multimap, @CheckForNull Object mutex) { if (multimap instanceof SynchronizedSortedSetMultimap) { return multimap; } return new SynchronizedSortedSetMultimap<>(multimap, mutex); } static final class SynchronizedSortedSetMultimap< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSetMultimap implements SortedSetMultimap { SynchronizedSortedSetMultimap(SortedSetMultimap delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override SortedSetMultimap delegate() { return (SortedSetMultimap) super.delegate(); } @Override public SortedSet get(K key) { synchronized (mutex) { return sortedSet(delegate().get(key), mutex); } } @Override public SortedSet removeAll(@CheckForNull Object key) { synchronized (mutex) { return delegate().removeAll(key); // copy not synchronized } } @Override public SortedSet replaceValues(K key, Iterable values) { synchronized (mutex) { return delegate().replaceValues(key, values); // copy not synchronized } } @Override @CheckForNull public Comparator valueComparator() { synchronized (mutex) { return delegate().valueComparator(); } } private static final long serialVersionUID = 0; } private static Collection typePreservingCollection( Collection collection, @CheckForNull Object mutex) { if (collection instanceof SortedSet) { return sortedSet((SortedSet) collection, mutex); } if (collection instanceof Set) { return set((Set) collection, mutex); } if (collection instanceof List) { return list((List) collection, mutex); } return collection(collection, mutex); } private static Set typePreservingSet( Set set, @CheckForNull Object mutex) { if (set instanceof SortedSet) { return sortedSet((SortedSet) set, mutex); } else { return set(set, mutex); } } static final class SynchronizedAsMapEntries< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSet>> { SynchronizedAsMapEntries( Set>> delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override public Iterator>> iterator() { // Must be manually synchronized. return new TransformedIterator>, Map.Entry>>( super.iterator()) { @Override Map.Entry> transform(final Map.Entry> entry) { return new ForwardingMapEntry>() { @Override protected Map.Entry> delegate() { return entry; } @Override public Collection getValue() { return typePreservingCollection(entry.getValue(), mutex); } }; } }; } // See Collections.CheckedMap.CheckedEntrySet for details on attacks. @Override public @Nullable Object[] toArray() { synchronized (mutex) { /* * toArrayImpl returns `@Nullable Object[]` rather than `Object[]` but only because it can * be used with collections that may contain null. This collection never contains nulls, so * we could return `Object[]`. But this class is private and J2KT cannot change return types * in overrides, so we declare `@Nullable Object[]` as the return type. */ return ObjectArrays.toArrayImpl(delegate()); } } @Override @SuppressWarnings("nullness") // b/192354773 in our checker affects toArray declarations public T[] toArray(T[] array) { synchronized (mutex) { return ObjectArrays.toArrayImpl(delegate(), array); } } @Override public boolean contains(@CheckForNull 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(@CheckForNull Object o) { if (o == this) { return true; } synchronized (mutex) { return Sets.equalsImpl(delegate(), o); } } @Override public boolean remove(@CheckForNull 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 Map map( Map map, @CheckForNull Object mutex) { return new SynchronizedMap<>(map, mutex); } static class SynchronizedMap extends SynchronizedObject implements Map { @CheckForNull transient Set keySet; @CheckForNull transient Collection values; @CheckForNull transient Set> entrySet; SynchronizedMap(Map delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @SuppressWarnings("unchecked") @Override Map delegate() { return (Map) super.delegate(); } @Override public void clear() { synchronized (mutex) { delegate().clear(); } } @Override public boolean containsKey(@CheckForNull Object key) { synchronized (mutex) { return delegate().containsKey(key); } } @Override public boolean containsValue(@CheckForNull Object value) { synchronized (mutex) { return delegate().containsValue(value); } } @Override public Set> entrySet() { synchronized (mutex) { if (entrySet == null) { entrySet = set(delegate().entrySet(), mutex); } return entrySet; } } @Override public void forEach(BiConsumer action) { synchronized (mutex) { delegate().forEach(action); } } @Override @CheckForNull public V get(@CheckForNull Object key) { synchronized (mutex) { return delegate().get(key); } } @Override @CheckForNull public V getOrDefault(@CheckForNull Object key, @CheckForNull V defaultValue) { synchronized (mutex) { return delegate().getOrDefault(key, defaultValue); } } @Override public boolean isEmpty() { synchronized (mutex) { return delegate().isEmpty(); } } @Override public Set keySet() { synchronized (mutex) { if (keySet == null) { keySet = set(delegate().keySet(), mutex); } return keySet; } } @Override @CheckForNull public V put(K key, V value) { synchronized (mutex) { return delegate().put(key, value); } } @Override @CheckForNull public V putIfAbsent(K key, V value) { synchronized (mutex) { return delegate().putIfAbsent(key, value); } } @Override public boolean replace(K key, V oldValue, V newValue) { synchronized (mutex) { return delegate().replace(key, oldValue, newValue); } } @Override @CheckForNull public V replace(K key, V value) { synchronized (mutex) { return delegate().replace(key, value); } } @Override public V computeIfAbsent(K key, Function mappingFunction) { synchronized (mutex) { return delegate().computeIfAbsent(key, mappingFunction); } } @Override @CheckForNull public V computeIfPresent( K key, BiFunction remappingFunction) { synchronized (mutex) { return delegate().computeIfPresent(key, remappingFunction); } } @Override @CheckForNull public V compute( K key, BiFunction remappingFunction) { synchronized (mutex) { return delegate().compute(key, remappingFunction); } } @Override @CheckForNull public V merge( K key, @NonNull V value, BiFunction remappingFunction) { synchronized (mutex) { return delegate().merge(key, value, remappingFunction); } } @Override public void putAll(Map map) { synchronized (mutex) { delegate().putAll(map); } } @Override public void replaceAll(BiFunction function) { synchronized (mutex) { delegate().replaceAll(function); } } @Override @CheckForNull public V remove(@CheckForNull Object key) { synchronized (mutex) { return delegate().remove(key); } } @Override public boolean remove(@CheckForNull Object key, @CheckForNull Object value) { synchronized (mutex) { return delegate().remove(key, value); } } @Override public int size() { synchronized (mutex) { return delegate().size(); } } @Override public Collection values() { synchronized (mutex) { if (values == null) { values = collection(delegate().values(), mutex); } return values; } } @Override public boolean equals(@CheckForNull 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 SortedMap sortedMap( SortedMap sortedMap, @CheckForNull Object mutex) { return new SynchronizedSortedMap<>(sortedMap, mutex); } static class SynchronizedSortedMap extends SynchronizedMap implements SortedMap { SynchronizedSortedMap(SortedMap delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override SortedMap delegate() { return (SortedMap) super.delegate(); } @Override @CheckForNull public Comparator comparator() { synchronized (mutex) { return delegate().comparator(); } } @Override public K firstKey() { synchronized (mutex) { return delegate().firstKey(); } } @Override public SortedMap headMap(K toKey) { synchronized (mutex) { return sortedMap(delegate().headMap(toKey), mutex); } } @Override public K lastKey() { synchronized (mutex) { return delegate().lastKey(); } } @Override public SortedMap subMap(K fromKey, K toKey) { synchronized (mutex) { return sortedMap(delegate().subMap(fromKey, toKey), mutex); } } @Override public SortedMap tailMap(K fromKey) { synchronized (mutex) { return sortedMap(delegate().tailMap(fromKey), mutex); } } private static final long serialVersionUID = 0; } static BiMap biMap( BiMap bimap, @CheckForNull Object mutex) { if (bimap instanceof SynchronizedBiMap || bimap instanceof ImmutableBiMap) { return bimap; } return new SynchronizedBiMap<>(bimap, mutex, null); } static final class SynchronizedBiMap extends SynchronizedMap implements BiMap, Serializable { @CheckForNull private transient Set valueSet; @RetainedWith @CheckForNull private transient BiMap inverse; private SynchronizedBiMap( BiMap delegate, @CheckForNull Object mutex, @CheckForNull BiMap inverse) { super(delegate, mutex); this.inverse = inverse; } @Override BiMap delegate() { return (BiMap) super.delegate(); } @Override public Set values() { synchronized (mutex) { if (valueSet == null) { valueSet = set(delegate().values(), mutex); } return valueSet; } } @Override @CheckForNull public V forcePut(@ParametricNullness K key, @ParametricNullness V value) { synchronized (mutex) { return delegate().forcePut(key, value); } } @Override public BiMap inverse() { synchronized (mutex) { if (inverse == null) { inverse = new SynchronizedBiMap<>(delegate().inverse(), mutex, this); } return inverse; } } private static final long serialVersionUID = 0; } static final class SynchronizedAsMap extends SynchronizedMap> { @CheckForNull transient Set>> asMapEntrySet; @CheckForNull transient Collection> asMapValues; SynchronizedAsMap(Map> delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override @CheckForNull public Collection get(@CheckForNull Object key) { synchronized (mutex) { Collection collection = super.get(key); return (collection == null) ? null : typePreservingCollection(collection, mutex); } } @Override public Set>> entrySet() { synchronized (mutex) { if (asMapEntrySet == null) { asMapEntrySet = new SynchronizedAsMapEntries<>(delegate().entrySet(), mutex); } return asMapEntrySet; } } @Override public Collection> values() { synchronized (mutex) { if (asMapValues == null) { asMapValues = new SynchronizedAsMapValues(delegate().values(), mutex); } return asMapValues; } } @Override public boolean containsValue(@CheckForNull Object o) { // values() and its contains() method are both synchronized. return values().contains(o); } private static final long serialVersionUID = 0; } static final class SynchronizedAsMapValues extends SynchronizedCollection> { SynchronizedAsMapValues(Collection> delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override public Iterator> iterator() { // Must be manually synchronized. return new TransformedIterator, Collection>(super.iterator()) { @Override Collection transform(Collection from) { return typePreservingCollection(from, mutex); } }; } private static final long serialVersionUID = 0; } @GwtIncompatible // NavigableSet @VisibleForTesting static final class SynchronizedNavigableSet extends SynchronizedSortedSet implements NavigableSet { SynchronizedNavigableSet(NavigableSet delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override NavigableSet delegate() { return (NavigableSet) super.delegate(); } @Override @CheckForNull public E ceiling(E e) { synchronized (mutex) { return delegate().ceiling(e); } } @Override public Iterator descendingIterator() { return delegate().descendingIterator(); // manually synchronized } @CheckForNull transient NavigableSet descendingSet; @Override public NavigableSet descendingSet() { synchronized (mutex) { if (descendingSet == null) { NavigableSet dS = Synchronized.navigableSet(delegate().descendingSet(), mutex); descendingSet = dS; return dS; } return descendingSet; } } @Override @CheckForNull public E floor(E e) { synchronized (mutex) { return delegate().floor(e); } } @Override public NavigableSet headSet(E toElement, boolean inclusive) { synchronized (mutex) { return Synchronized.navigableSet(delegate().headSet(toElement, inclusive), mutex); } } @Override public SortedSet headSet(E toElement) { return headSet(toElement, false); } @Override @CheckForNull public E higher(E e) { synchronized (mutex) { return delegate().higher(e); } } @Override @CheckForNull public E lower(E e) { synchronized (mutex) { return delegate().lower(e); } } @Override @CheckForNull public E pollFirst() { synchronized (mutex) { return delegate().pollFirst(); } } @Override @CheckForNull public E pollLast() { synchronized (mutex) { return delegate().pollLast(); } } @Override public NavigableSet subSet( E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { synchronized (mutex) { return Synchronized.navigableSet( delegate().subSet(fromElement, fromInclusive, toElement, toInclusive), mutex); } } @Override public SortedSet subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } @Override public NavigableSet tailSet(E fromElement, boolean inclusive) { synchronized (mutex) { return Synchronized.navigableSet(delegate().tailSet(fromElement, inclusive), mutex); } } @Override public SortedSet tailSet(E fromElement) { return tailSet(fromElement, true); } private static final long serialVersionUID = 0; } @GwtIncompatible // NavigableSet static NavigableSet navigableSet( NavigableSet navigableSet, @CheckForNull Object mutex) { return new SynchronizedNavigableSet<>(navigableSet, mutex); } @GwtIncompatible // NavigableSet static NavigableSet navigableSet(NavigableSet navigableSet) { return navigableSet(navigableSet, null); } @GwtIncompatible // NavigableMap static NavigableMap navigableMap( NavigableMap navigableMap) { return navigableMap(navigableMap, null); } @GwtIncompatible // NavigableMap static NavigableMap navigableMap( NavigableMap navigableMap, @CheckForNull Object mutex) { return new SynchronizedNavigableMap<>(navigableMap, mutex); } @GwtIncompatible // NavigableMap @VisibleForTesting static final class SynchronizedNavigableMap< K extends @Nullable Object, V extends @Nullable Object> extends SynchronizedSortedMap implements NavigableMap { SynchronizedNavigableMap(NavigableMap delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override NavigableMap delegate() { return (NavigableMap) super.delegate(); } @Override @CheckForNull public Map.Entry ceilingEntry(K key) { synchronized (mutex) { return nullableSynchronizedEntry(delegate().ceilingEntry(key), mutex); } } @Override @CheckForNull public K ceilingKey(K key) { synchronized (mutex) { return delegate().ceilingKey(key); } } @CheckForNull transient NavigableSet descendingKeySet; @Override public NavigableSet descendingKeySet() { synchronized (mutex) { if (descendingKeySet == null) { return descendingKeySet = Synchronized.navigableSet(delegate().descendingKeySet(), mutex); } return descendingKeySet; } } @CheckForNull transient NavigableMap descendingMap; @Override public NavigableMap descendingMap() { synchronized (mutex) { if (descendingMap == null) { return descendingMap = navigableMap(delegate().descendingMap(), mutex); } return descendingMap; } } @Override @CheckForNull public Map.Entry firstEntry() { synchronized (mutex) { return nullableSynchronizedEntry(delegate().firstEntry(), mutex); } } @Override @CheckForNull public Map.Entry floorEntry(K key) { synchronized (mutex) { return nullableSynchronizedEntry(delegate().floorEntry(key), mutex); } } @Override @CheckForNull public K floorKey(K key) { synchronized (mutex) { return delegate().floorKey(key); } } @Override public NavigableMap headMap(K toKey, boolean inclusive) { synchronized (mutex) { return navigableMap(delegate().headMap(toKey, inclusive), mutex); } } @Override public SortedMap headMap(K toKey) { return headMap(toKey, false); } @Override @CheckForNull public Map.Entry higherEntry(K key) { synchronized (mutex) { return nullableSynchronizedEntry(delegate().higherEntry(key), mutex); } } @Override @CheckForNull public K higherKey(K key) { synchronized (mutex) { return delegate().higherKey(key); } } @Override @CheckForNull public Map.Entry lastEntry() { synchronized (mutex) { return nullableSynchronizedEntry(delegate().lastEntry(), mutex); } } @Override @CheckForNull public Map.Entry lowerEntry(K key) { synchronized (mutex) { return nullableSynchronizedEntry(delegate().lowerEntry(key), mutex); } } @Override @CheckForNull public K lowerKey(K key) { synchronized (mutex) { return delegate().lowerKey(key); } } @Override public Set keySet() { return navigableKeySet(); } @CheckForNull transient NavigableSet navigableKeySet; @Override public NavigableSet navigableKeySet() { synchronized (mutex) { if (navigableKeySet == null) { return navigableKeySet = Synchronized.navigableSet(delegate().navigableKeySet(), mutex); } return navigableKeySet; } } @Override @CheckForNull public Map.Entry pollFirstEntry() { synchronized (mutex) { return nullableSynchronizedEntry(delegate().pollFirstEntry(), mutex); } } @Override @CheckForNull public Map.Entry pollLastEntry() { synchronized (mutex) { return nullableSynchronizedEntry(delegate().pollLastEntry(), mutex); } } @Override public NavigableMap subMap( K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { synchronized (mutex) { return navigableMap(delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), mutex); } } @Override public SortedMap subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } @Override public NavigableMap tailMap(K fromKey, boolean inclusive) { synchronized (mutex) { return navigableMap(delegate().tailMap(fromKey, inclusive), mutex); } } @Override public SortedMap tailMap(K fromKey) { return tailMap(fromKey, true); } private static final long serialVersionUID = 0; } @GwtIncompatible // works but is needed only for NavigableMap @CheckForNull private static Map.Entry nullableSynchronizedEntry( @CheckForNull Map.Entry entry, @CheckForNull Object mutex) { if (entry == null) { return null; } return new SynchronizedEntry<>(entry, mutex); } @GwtIncompatible // works but is needed only for NavigableMap static final class SynchronizedEntry extends SynchronizedObject implements Map.Entry { SynchronizedEntry(Map.Entry delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @SuppressWarnings("unchecked") // guaranteed by the constructor @Override Map.Entry delegate() { return (Map.Entry) super.delegate(); } @Override public boolean equals(@CheckForNull 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; } static Queue queue(Queue queue, @CheckForNull Object mutex) { return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue(queue, mutex); } static class SynchronizedQueue extends SynchronizedCollection implements Queue { SynchronizedQueue(Queue delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override Queue delegate() { return (Queue) super.delegate(); } @Override public E element() { synchronized (mutex) { return delegate().element(); } } @Override public boolean offer(E e) { synchronized (mutex) { return delegate().offer(e); } } @Override @CheckForNull public E peek() { synchronized (mutex) { return delegate().peek(); } } @Override @CheckForNull public E poll() { synchronized (mutex) { return delegate().poll(); } } @Override public E remove() { synchronized (mutex) { return delegate().remove(); } } private static final long serialVersionUID = 0; } static Deque deque(Deque deque, @CheckForNull Object mutex) { return new SynchronizedDeque<>(deque, mutex); } static final class SynchronizedDeque extends SynchronizedQueue implements Deque { SynchronizedDeque(Deque delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @Override Deque delegate() { return (Deque) super.delegate(); } @Override public void addFirst(E e) { synchronized (mutex) { delegate().addFirst(e); } } @Override public void addLast(E e) { synchronized (mutex) { delegate().addLast(e); } } @Override public boolean offerFirst(E e) { synchronized (mutex) { return delegate().offerFirst(e); } } @Override public boolean offerLast(E e) { synchronized (mutex) { return delegate().offerLast(e); } } @Override public E removeFirst() { synchronized (mutex) { return delegate().removeFirst(); } } @Override public E removeLast() { synchronized (mutex) { return delegate().removeLast(); } } @Override @CheckForNull public E pollFirst() { synchronized (mutex) { return delegate().pollFirst(); } } @Override @CheckForNull public E pollLast() { synchronized (mutex) { return delegate().pollLast(); } } @Override public E getFirst() { synchronized (mutex) { return delegate().getFirst(); } } @Override public E getLast() { synchronized (mutex) { return delegate().getLast(); } } @Override @CheckForNull public E peekFirst() { synchronized (mutex) { return delegate().peekFirst(); } } @Override @CheckForNull public E peekLast() { synchronized (mutex) { return delegate().peekLast(); } } @Override public boolean removeFirstOccurrence(@CheckForNull Object o) { synchronized (mutex) { return delegate().removeFirstOccurrence(o); } } @Override public boolean removeLastOccurrence(@CheckForNull Object o) { synchronized (mutex) { return delegate().removeLastOccurrence(o); } } @Override public void push(E e) { synchronized (mutex) { delegate().push(e); } } @Override public E pop() { synchronized (mutex) { return delegate().pop(); } } @Override public Iterator descendingIterator() { synchronized (mutex) { return delegate().descendingIterator(); } } private static final long serialVersionUID = 0; } static Table table(Table table, @CheckForNull Object mutex) { return new SynchronizedTable<>(table, mutex); } static final class SynchronizedTable< R extends @Nullable Object, C extends @Nullable Object, V extends @Nullable Object> extends SynchronizedObject implements Table { SynchronizedTable(Table delegate, @CheckForNull Object mutex) { super(delegate, mutex); } @SuppressWarnings("unchecked") @Override Table delegate() { return (Table) super.delegate(); } @Override public boolean contains(@CheckForNull Object rowKey, @CheckForNull Object columnKey) { synchronized (mutex) { return delegate().contains(rowKey, columnKey); } } @Override public boolean containsRow(@CheckForNull Object rowKey) { synchronized (mutex) { return delegate().containsRow(rowKey); } } @Override public boolean containsColumn(@CheckForNull Object columnKey) { synchronized (mutex) { return delegate().containsColumn(columnKey); } } @Override public boolean containsValue(@CheckForNull Object value) { synchronized (mutex) { return delegate().containsValue(value); } } @Override @CheckForNull public V get(@CheckForNull Object rowKey, @CheckForNull Object columnKey) { synchronized (mutex) { return delegate().get(rowKey, columnKey); } } @Override public boolean isEmpty() { synchronized (mutex) { return delegate().isEmpty(); } } @Override public int size() { synchronized (mutex) { return delegate().size(); } } @Override public void clear() { synchronized (mutex) { delegate().clear(); } } @Override @CheckForNull public V put( @ParametricNullness R rowKey, @ParametricNullness C columnKey, @ParametricNullness V value) { synchronized (mutex) { return delegate().put(rowKey, columnKey, value); } } @Override public void putAll(Table table) { synchronized (mutex) { delegate().putAll(table); } } @Override @CheckForNull public V remove(@CheckForNull Object rowKey, @CheckForNull Object columnKey) { synchronized (mutex) { return delegate().remove(rowKey, columnKey); } } @Override public Map row(@ParametricNullness R rowKey) { synchronized (mutex) { return map(delegate().row(rowKey), mutex); } } @Override public Map column(@ParametricNullness C columnKey) { synchronized (mutex) { return map(delegate().column(columnKey), mutex); } } @Override public Set> cellSet() { synchronized (mutex) { return set(delegate().cellSet(), mutex); } } @Override public Set rowKeySet() { synchronized (mutex) { return set(delegate().rowKeySet(), mutex); } } @Override public Set columnKeySet() { synchronized (mutex) { return set(delegate().columnKeySet(), mutex); } } @Override public Collection values() { synchronized (mutex) { return collection(delegate().values(), mutex); } } @Override public Map> rowMap() { synchronized (mutex) { return map( Maps.transformValues( delegate().rowMap(), new com.google.common.base.Function, Map>() { @Override public Map apply(Map t) { return map(t, mutex); } }), mutex); } } @Override public Map> columnMap() { synchronized (mutex) { return map( Maps.transformValues( delegate().columnMap(), new com.google.common.base.Function, Map>() { @Override public Map apply(Map t) { return map(t, mutex); } }), mutex); } } @Override public int hashCode() { synchronized (mutex) { return delegate().hashCode(); } } @Override public boolean equals(@CheckForNull Object obj) { if (this == obj) { return true; } synchronized (mutex) { return delegate().equals(obj); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy