1834 lines
40 KiB
Java
1834 lines
40 KiB
Java
/*
|
|
* 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 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.Map.Entry;
|
|
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 javax.annotation.Nullable;
|
|
|
|
import com.google.common.annotations.GwtCompatible;
|
|
import com.google.common.annotations.GwtIncompatible;
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
static <E> Queue<E> queue(Queue<E> queue, @Nullable Object mutex) {
|
|
return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue<E>(queue, mutex);
|
|
}
|
|
|
|
private static class SynchronizedQueue<E> extends SynchronizedCollection<E> implements Queue<E> {
|
|
|
|
SynchronizedQueue(Queue<E> delegate, @Nullable Object mutex) {
|
|
super(delegate, mutex);
|
|
}
|
|
|
|
@Override
|
|
Queue<E> delegate() {
|
|
return (Queue<E>) super.delegate();
|
|
}
|
|
|
|
@Override
|
|
public E element() {
|
|
synchronized (mutex) {
|
|
return delegate().element();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean offer(E e) {
|
|
synchronized (mutex) {
|
|
return delegate().offer(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public E peek() {
|
|
synchronized (mutex) {
|
|
return delegate().peek();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public E poll() {
|
|
synchronized (mutex) {
|
|
return delegate().poll();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public E remove() {
|
|
synchronized (mutex) {
|
|
return delegate().remove();
|
|
}
|
|
}
|
|
|
|
private static final long serialVersionUID = 0;
|
|
}
|
|
|
|
@GwtIncompatible("Deque")
|
|
static <E> Deque<E> deque(Deque<E> deque, @Nullable Object mutex) {
|
|
return new SynchronizedDeque<E>(deque, mutex);
|
|
}
|
|
|
|
@GwtIncompatible("Deque")
|
|
private static final class SynchronizedDeque<E> extends SynchronizedQueue<E> implements Deque<E> {
|
|
|
|
SynchronizedDeque(Deque<E> delegate, @Nullable Object mutex) {
|
|
super(delegate, mutex);
|
|
}
|
|
|
|
@Override
|
|
Deque<E> delegate() {
|
|
return (Deque<E>) 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
|
|
public E pollFirst() {
|
|
synchronized (mutex) {
|
|
return delegate().pollFirst();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
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
|
|
public E peekFirst() {
|
|
synchronized (mutex) {
|
|
return delegate().peekFirst();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public E peekLast() {
|
|
synchronized (mutex) {
|
|
return delegate().peekLast();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean removeFirstOccurrence(Object o) {
|
|
synchronized (mutex) {
|
|
return delegate().removeFirstOccurrence(o);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean removeLastOccurrence(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<E> descendingIterator() {
|
|
synchronized (mutex) {
|
|
return delegate().descendingIterator();
|
|
}
|
|
}
|
|
|
|
private static final long serialVersionUID = 0;
|
|
}
|
|
}
|