1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.annotations.GwtIncompatible; 21 22 import java.io.IOException; 23 import java.io.ObjectOutputStream; 24 import java.io.Serializable; 25 import java.util.Collection; 26 import java.util.Comparator; 27 import java.util.Iterator; 28 import java.util.List; 29 import java.util.ListIterator; 30 import java.util.Map; 31 import java.util.RandomAccess; 32 import java.util.Set; 33 import java.util.SortedSet; 34 35 import javax.annotation.Nullable; 36 37 import static com.google.common.base.Preconditions.checkNotNull; 38 39 /** 40 * Synchronized collection views. The returned synchronized collection views are 41 * serializable if the backing collection and the mutex are serializable. 42 * 43 * <p>If a {@code null} is passed as the {@code mutex} parameter to any of this 44 * class's top-level methods or inner class constructors, the created object 45 * uses itself as the synchronization mutex. 46 * 47 * <p>This class should be used by other collection classes only. 48 * 49 * @author Mike Bostock 50 * @author Jared Levy 51 */ 52 @GwtCompatible 53 final class Synchronized { 54 private Synchronized() {} 55 56 /** Abstract base class for synchronized views. */ 57 static class SynchronizedObject implements Serializable { 58 private final Object delegate; 59 protected final Object mutex; 60 61 public SynchronizedObject(Object delegate, @Nullable Object mutex) { 62 this.delegate = checkNotNull(delegate); 63 this.mutex = (mutex == null) ? this : mutex; 64 } 65 66 protected Object delegate() { 67 return delegate; 68 } 69 70 // No equals and hashCode; see ForwardingObject for details. 71 72 @Override public String toString() { 73 synchronized (mutex) { 74 return delegate.toString(); 75 } 76 } 77 78 // Serialization invokes writeObject only when it's private. 79 // The SynchronizedObject subclasses don't need a writeObject method since 80 // they don't contain any non-transient member variables, while the 81 // following writeObject() handles the SynchronizedObject members. 82 83 private void writeObject(ObjectOutputStream stream) throws IOException { 84 synchronized (mutex) { 85 stream.defaultWriteObject(); 86 } 87 } 88 89 private static final long serialVersionUID = 0; 90 } 91 92 /** 93 * Returns a synchronized (thread-safe) collection backed by the specified 94 * collection using the specified mutex. In order to guarantee serial access, 95 * it is critical that <b>all</b> access to the backing collection is 96 * accomplished through the returned collection. 97 * 98 * <p>It is imperative that the user manually synchronize on the specified 99 * mutex when iterating over the returned collection: <pre> {@code 100 * 101 * Collection<E> s = Synchronized.collection( 102 * new HashSet<E>(), mutex); 103 * ... 104 * synchronized (mutex) { 105 * Iterator<E> i = s.iterator(); // Must be in synchronized block 106 * while (i.hasNext()) { 107 * foo(i.next()); 108 * } 109 * }}</pre> 110 * 111 * Failure to follow this advice may result in non-deterministic behavior. 112 * 113 * @param collection the collection to be wrapped in a synchronized view 114 * @return a synchronized view of the specified collection 115 */ 116 static <E> Collection<E> collection( 117 Collection<E> collection, @Nullable Object mutex) { 118 return new SynchronizedCollection<E>(collection, mutex); 119 } 120 121 /** @see Synchronized#collection */ 122 static class SynchronizedCollection<E> extends SynchronizedObject 123 implements Collection<E> { 124 public SynchronizedCollection( 125 Collection<E> delegate, @Nullable Object mutex) { 126 super(delegate, mutex); 127 } 128 129 @SuppressWarnings("unchecked") 130 @Override protected Collection<E> delegate() { 131 return (Collection<E>) super.delegate(); 132 } 133 134 public boolean add(E e) { 135 synchronized (mutex) { 136 return delegate().add(e); 137 } 138 } 139 140 public boolean addAll(Collection<? extends E> c) { 141 synchronized (mutex) { 142 return delegate().addAll(c); 143 } 144 } 145 146 public void clear() { 147 synchronized (mutex) { 148 delegate().clear(); 149 } 150 } 151 152 public boolean contains(Object o) { 153 synchronized (mutex) { 154 return delegate().contains(o); 155 } 156 } 157 158 public boolean containsAll(Collection<?> c) { 159 synchronized (mutex) { 160 return delegate().containsAll(c); 161 } 162 } 163 164 public boolean isEmpty() { 165 synchronized (mutex) { 166 return delegate().isEmpty(); 167 } 168 } 169 170 public Iterator<E> iterator() { 171 return delegate().iterator(); // manually synchronized 172 } 173 174 public boolean remove(Object o) { 175 synchronized (mutex) { 176 return delegate().remove(o); 177 } 178 } 179 180 public boolean removeAll(Collection<?> c) { 181 synchronized (mutex) { 182 return delegate().removeAll(c); 183 } 184 } 185 186 public boolean retainAll(Collection<?> c) { 187 synchronized (mutex) { 188 return delegate().retainAll(c); 189 } 190 } 191 192 public int size() { 193 synchronized (mutex) { 194 return delegate().size(); 195 } 196 } 197 198 public Object[] toArray() { 199 synchronized (mutex) { 200 return delegate().toArray(); 201 } 202 } 203 204 public <T> T[] toArray(T[] a) { 205 synchronized (mutex) { 206 return delegate().toArray(a); 207 } 208 } 209 210 private static final long serialVersionUID = 0; 211 } 212 213 /** 214 * Returns a synchronized (thread-safe) set backed by the specified set using 215 * the specified mutex. In order to guarantee serial access, it is critical 216 * that <b>all</b> access to the backing set is accomplished through the 217 * returned set. 218 * 219 * <p>It is imperative that the user manually synchronize on the specified 220 * mutex when iterating over the returned set: <pre> {@code 221 * 222 * Set<E> s = Synchronized.set(new HashSet<E>(), mutex); 223 * ... 224 * synchronized (mutex) { 225 * Iterator<E> i = s.iterator(); // Must be in synchronized block 226 * while (i.hasNext()) { 227 * foo(i.next()); 228 * } 229 * }}</pre> 230 * 231 * Failure to follow this advice may result in non-deterministic behavior. 232 * 233 * @param set the set to be wrapped in a synchronized view 234 * @return a synchronized view of the specified set 235 */ 236 public static <E> Set<E> set(Set<E> set, @Nullable Object mutex) { 237 return new SynchronizedSet<E>(set, mutex); 238 } 239 240 /** @see Synchronized#set */ 241 static class SynchronizedSet<E> extends SynchronizedCollection<E> 242 implements Set<E> { 243 public SynchronizedSet(Set<E> delegate, @Nullable Object mutex) { 244 super(delegate, mutex); 245 } 246 247 @Override protected Set<E> delegate() { 248 return (Set<E>) super.delegate(); 249 } 250 251 @Override public boolean equals(Object o) { 252 if (o == this) { 253 return true; 254 } 255 synchronized (mutex) { 256 return delegate().equals(o); 257 } 258 } 259 260 @Override public int hashCode() { 261 synchronized (mutex) { 262 return delegate().hashCode(); 263 } 264 } 265 266 private static final long serialVersionUID = 0; 267 } 268 269 /** 270 * Returns a synchronized (thread-safe) sorted set backed by the specified 271 * sorted set using the specified mutex. In order to guarantee serial access, 272 * it is critical that <b>all</b> access to the backing sorted set is 273 * accomplished through the returned sorted set. 274 * 275 * <p>It is imperative that the user manually synchronize on the specified 276 * mutex when iterating over the returned sorted set: <pre> {@code 277 * 278 * SortedSet<E> s = Synchronized.sortedSet( 279 * new TreeSet<E>(), mutex); 280 * ... 281 * synchronized (mutex) { 282 * Iterator<E> i = s.iterator(); // Must be in synchronized block 283 * while (i.hasNext()) { 284 * foo(i.next()); 285 * } 286 * }}</pre> 287 * 288 * Failure to follow this advice may result in non-deterministic behavior. 289 * 290 * @param set the sorted set to be wrapped in a synchronized view 291 * @return a synchronized view of the specified sorted set 292 */ 293 static <E> SortedSet<E> sortedSet(SortedSet<E> set, @Nullable Object mutex) { 294 return new SynchronizedSortedSet<E>(set, mutex); 295 } 296 297 /** @see Synchronized#sortedSet */ 298 static class SynchronizedSortedSet<E> extends SynchronizedSet<E> 299 implements SortedSet<E> { 300 public SynchronizedSortedSet( 301 SortedSet<E> delegate, @Nullable Object mutex) { 302 super(delegate, mutex); 303 } 304 305 @Override protected SortedSet<E> delegate() { 306 return (SortedSet<E>) super.delegate(); 307 } 308 309 public Comparator<? super E> comparator() { 310 synchronized (mutex) { 311 return delegate().comparator(); 312 } 313 } 314 315 public SortedSet<E> subSet(E fromElement, E toElement) { 316 synchronized (mutex) { 317 return sortedSet(delegate().subSet(fromElement, toElement), mutex); 318 } 319 } 320 321 public SortedSet<E> headSet(E toElement) { 322 synchronized (mutex) { 323 return sortedSet(delegate().headSet(toElement), mutex); 324 } 325 } 326 327 public SortedSet<E> tailSet(E fromElement) { 328 synchronized (mutex) { 329 return sortedSet(delegate().tailSet(fromElement), mutex); 330 } 331 } 332 333 public E first() { 334 synchronized (mutex) { 335 return delegate().first(); 336 } 337 } 338 339 public E last() { 340 synchronized (mutex) { 341 return delegate().last(); 342 } 343 } 344 345 private static final long serialVersionUID = 0; 346 } 347 348 /** 349 * Returns a synchronized (thread-safe) list backed by the specified list 350 * using the specified mutex. In order to guarantee serial access, it is 351 * critical that <b>all</b> access to the backing list is accomplished 352 * through the returned list. 353 * 354 * <p>It is imperative that the user manually synchronize on the specified 355 * mutex when iterating over the returned list: <pre> {@code 356 * 357 * List<E> l = Synchronized.list(new ArrayList<E>(), mutex); 358 * ... 359 * synchronized (mutex) { 360 * Iterator<E> i = l.iterator(); // Must be in synchronized block 361 * while (i.hasNext()) { 362 * foo(i.next()); 363 * } 364 * }}</pre> 365 * 366 * Failure to follow this advice may result in non-deterministic behavior. 367 * 368 * <p>The returned list implements {@link RandomAccess} if the specified list 369 * implements {@code RandomAccess}. 370 * 371 * @param list the list to be wrapped in a synchronized view 372 * @return a synchronized view of the specified list 373 */ 374 static <E> List<E> list(List<E> list, @Nullable Object mutex) { 375 return (list instanceof RandomAccess) 376 ? new SynchronizedRandomAccessList<E>(list, mutex) 377 : new SynchronizedList<E>(list, mutex); 378 } 379 380 /** @see Synchronized#list */ 381 static class SynchronizedList<E> extends SynchronizedCollection<E> 382 implements List<E> { 383 public SynchronizedList(List<E> delegate, @Nullable Object mutex) { 384 super(delegate, mutex); 385 } 386 387 @Override protected List<E> delegate() { 388 return (List<E>) super.delegate(); 389 } 390 391 public void add(int index, E element) { 392 synchronized (mutex) { 393 delegate().add(index, element); 394 } 395 } 396 397 public boolean addAll(int index, Collection<? extends E> c) { 398 synchronized (mutex) { 399 return delegate().addAll(index, c); 400 } 401 } 402 403 public E get(int index) { 404 synchronized (mutex) { 405 return delegate().get(index); 406 } 407 } 408 409 public int indexOf(Object o) { 410 synchronized (mutex) { 411 return delegate().indexOf(o); 412 } 413 } 414 415 public int lastIndexOf(Object o) { 416 synchronized (mutex) { 417 return delegate().lastIndexOf(o); 418 } 419 } 420 421 public ListIterator<E> listIterator() { 422 return delegate().listIterator(); // manually synchronized 423 } 424 425 public ListIterator<E> listIterator(int index) { 426 return delegate().listIterator(index); // manually synchronized 427 } 428 429 public E remove(int index) { 430 synchronized (mutex) { 431 return delegate().remove(index); 432 } 433 } 434 435 public E set(int index, E element) { 436 synchronized (mutex) { 437 return delegate().set(index, element); 438 } 439 } 440 441 @GwtIncompatible("List.subList") 442 public List<E> subList(int fromIndex, int toIndex) { 443 synchronized (mutex) { 444 return list(Platform.subList(delegate(), fromIndex, toIndex), mutex); 445 } 446 } 447 448 @Override public boolean equals(Object o) { 449 if (o == this) { 450 return true; 451 } 452 synchronized (mutex) { 453 return delegate().equals(o); 454 } 455 } 456 457 @Override public int hashCode() { 458 synchronized (mutex) { 459 return delegate().hashCode(); 460 } 461 } 462 463 private static final long serialVersionUID = 0; 464 } 465 466 /** @see Synchronized#list */ 467 static class SynchronizedRandomAccessList<E> extends SynchronizedList<E> 468 implements RandomAccess { 469 public SynchronizedRandomAccessList(List<E> list, @Nullable Object mutex) { 470 super(list, mutex); 471 } 472 private static final long serialVersionUID = 0; 473 } 474 475 /** 476 * Returns a synchronized (thread-safe) multiset backed by the specified 477 * multiset using the specified mutex. In order to guarantee serial access, it 478 * is critical that <b>all</b> access to the backing multiset is accomplished 479 * through the returned multiset. 480 * 481 * <p>It is imperative that the user manually synchronize on the specified 482 * mutex when iterating over the returned multiset: <pre> {@code 483 * 484 * Multiset<E> s = Synchronized.multiset( 485 * HashMultiset.<E>create(), mutex); 486 * ... 487 * synchronized (mutex) { 488 * Iterator<E> i = s.iterator(); // Must be in synchronized block 489 * while (i.hasNext()) { 490 * foo(i.next()); 491 * } 492 * }}</pre> 493 * 494 * Failure to follow this advice may result in non-deterministic behavior. 495 * 496 * @param multiset the multiset to be wrapped 497 * @return a synchronized view of the specified multiset 498 */ 499 private static <E> Multiset<E> multiset( 500 Multiset<E> multiset, @Nullable Object mutex) { 501 return new SynchronizedMultiset<E>(multiset, mutex); 502 } 503 504 /** @see Synchronized#multiset */ 505 static class SynchronizedMultiset<E> extends SynchronizedCollection<E> 506 implements Multiset<E> { 507 private transient Set<E> elementSet; 508 private transient Set<Entry<E>> entrySet; 509 510 public SynchronizedMultiset(Multiset<E> delegate, @Nullable Object mutex) { 511 super(delegate, mutex); 512 } 513 514 @Override protected Multiset<E> delegate() { 515 return (Multiset<E>) super.delegate(); 516 } 517 518 public int count(Object o) { 519 synchronized (mutex) { 520 return delegate().count(o); 521 } 522 } 523 524 public int add(E e, int n) { 525 synchronized (mutex) { 526 return delegate().add(e, n); 527 } 528 } 529 530 public int remove(Object o, int n) { 531 synchronized (mutex) { 532 return delegate().remove(o, n); 533 } 534 } 535 536 public int setCount(E element, int count) { 537 synchronized (mutex) { 538 return delegate().setCount(element, count); 539 } 540 } 541 542 public boolean setCount(E element, int oldCount, int newCount) { 543 synchronized (mutex) { 544 return delegate().setCount(element, oldCount, newCount); 545 } 546 } 547 548 public Set<E> elementSet() { 549 synchronized (mutex) { 550 if (elementSet == null) { 551 elementSet = typePreservingSet(delegate().elementSet(), mutex); 552 } 553 return elementSet; 554 } 555 } 556 557 public Set<Entry<E>> entrySet() { 558 synchronized (mutex) { 559 if (entrySet == null) { 560 entrySet = typePreservingSet(delegate().entrySet(), mutex); 561 } 562 return entrySet; 563 } 564 } 565 566 @Override public boolean equals(Object o) { 567 if (o == this) { 568 return true; 569 } 570 synchronized (mutex) { 571 return delegate().equals(o); 572 } 573 } 574 575 @Override public int hashCode() { 576 synchronized (mutex) { 577 return delegate().hashCode(); 578 } 579 } 580 581 private static final long serialVersionUID = 0; 582 } 583 584 /** 585 * Returns a synchronized (thread-safe) multimap backed by the specified 586 * multimap using the specified mutex. In order to guarantee serial access, it 587 * is critical that <b>all</b> access to the backing multimap is accomplished 588 * through the returned multimap. 589 * 590 * <p>It is imperative that the user manually synchronize on the specified 591 * mutex when accessing any of the return multimap's collection views: 592 * <pre> {@code 593 * 594 * Multimap<K, V> m = Synchronized.multimap( 595 * HashMultimap.create(), mutex); 596 * ... 597 * Set<K> s = m.keySet(); // Needn't be in synchronized block 598 * ... 599 * synchronized (mutex) { 600 * Iterator<K> i = s.iterator(); // Must be in synchronized block 601 * while (i.hasNext()) { 602 * foo(i.next()); 603 * } 604 * }}</pre> 605 * 606 * Failure to follow this advice may result in non-deterministic behavior. 607 * 608 * @param multimap the multimap to be wrapped in a synchronized view 609 * @return a synchronized view of the specified multimap 610 */ 611 public static <K, V> Multimap<K, V> multimap( 612 Multimap<K, V> multimap, @Nullable Object mutex) { 613 return new SynchronizedMultimap<K, V>(multimap, mutex); 614 } 615 616 /** @see Synchronized#multimap */ 617 private static class SynchronizedMultimap<K, V> extends SynchronizedObject 618 implements Multimap<K, V> { 619 transient Set<K> keySet; 620 transient Collection<V> valuesCollection; 621 transient Collection<Map.Entry<K, V>> entries; 622 transient Map<K, Collection<V>> asMap; 623 transient Multiset<K> keys; 624 625 @SuppressWarnings("unchecked") 626 @Override protected Multimap<K, V> delegate() { 627 return (Multimap<K, V>) super.delegate(); 628 } 629 630 SynchronizedMultimap(Multimap<K, V> delegate, @Nullable Object mutex) { 631 super(delegate, mutex); 632 } 633 634 public int size() { 635 synchronized (mutex) { 636 return delegate().size(); 637 } 638 } 639 640 public boolean isEmpty() { 641 synchronized (mutex) { 642 return delegate().isEmpty(); 643 } 644 } 645 646 public boolean containsKey(Object key) { 647 synchronized (mutex) { 648 return delegate().containsKey(key); 649 } 650 } 651 652 public boolean containsValue(Object value) { 653 synchronized (mutex) { 654 return delegate().containsValue(value); 655 } 656 } 657 658 public boolean containsEntry(Object key, Object value) { 659 synchronized (mutex) { 660 return delegate().containsEntry(key, value); 661 } 662 } 663 664 public Collection<V> get(K key) { 665 synchronized (mutex) { 666 return typePreservingCollection(delegate().get(key), mutex); 667 } 668 } 669 670 public boolean put(K key, V value) { 671 synchronized (mutex) { 672 return delegate().put(key, value); 673 } 674 } 675 676 public boolean putAll(K key, Iterable<? extends V> values) { 677 synchronized (mutex) { 678 return delegate().putAll(key, values); 679 } 680 } 681 682 public boolean putAll(Multimap<? extends K, ? extends V> multimap) { 683 synchronized (mutex) { 684 return delegate().putAll(multimap); 685 } 686 } 687 688 public Collection<V> replaceValues(K key, Iterable<? extends V> values) { 689 synchronized (mutex) { 690 return delegate().replaceValues(key, values); // copy not synchronized 691 } 692 } 693 694 public boolean remove(Object key, Object value) { 695 synchronized (mutex) { 696 return delegate().remove(key, value); 697 } 698 } 699 700 public Collection<V> removeAll(Object key) { 701 synchronized (mutex) { 702 return delegate().removeAll(key); // copy not synchronized 703 } 704 } 705 706 public void clear() { 707 synchronized (mutex) { 708 delegate().clear(); 709 } 710 } 711 712 public Set<K> keySet() { 713 synchronized (mutex) { 714 if (keySet == null) { 715 keySet = typePreservingSet(delegate().keySet(), mutex); 716 } 717 return keySet; 718 } 719 } 720 721 public Collection<V> values() { 722 synchronized (mutex) { 723 if (valuesCollection == null) { 724 valuesCollection = collection(delegate().values(), mutex); 725 } 726 return valuesCollection; 727 } 728 } 729 730 public Collection<Map.Entry<K, V>> entries() { 731 synchronized (mutex) { 732 if (entries == null) { 733 entries = typePreservingCollection(delegate().entries(), mutex); 734 } 735 return entries; 736 } 737 } 738 739 public Map<K, Collection<V>> asMap() { 740 synchronized (mutex) { 741 if (asMap == null) { 742 asMap = new SynchronizedAsMap<K, V>(delegate().asMap(), mutex); 743 } 744 return asMap; 745 } 746 } 747 748 public Multiset<K> keys() { 749 synchronized (mutex) { 750 if (keys == null) { 751 keys = multiset(delegate().keys(), mutex); 752 } 753 return keys; 754 } 755 } 756 757 @Override public boolean equals(Object o) { 758 if (o == this) { 759 return true; 760 } 761 synchronized (mutex) { 762 return delegate().equals(o); 763 } 764 } 765 766 @Override public int hashCode() { 767 synchronized (mutex) { 768 return delegate().hashCode(); 769 } 770 } 771 772 private static final long serialVersionUID = 0; 773 } 774 775 /** 776 * Returns a synchronized (thread-safe) list multimap backed by the specified 777 * multimap using the specified mutex. 778 * 779 * <p>You must follow the warnings described for {@link #multimap}. 780 * 781 * @param multimap the multimap to be wrapped in a synchronized view 782 * @return a synchronized view of the specified multimap 783 */ 784 public static <K, V> ListMultimap<K, V> listMultimap( 785 ListMultimap<K, V> multimap, @Nullable Object mutex) { 786 return new SynchronizedListMultimap<K, V>(multimap, mutex); 787 } 788 789 /** @see Synchronized#listMultimap */ 790 private static class SynchronizedListMultimap<K, V> 791 extends SynchronizedMultimap<K, V> implements ListMultimap<K, V> { 792 SynchronizedListMultimap( 793 ListMultimap<K, V> delegate, @Nullable Object mutex) { 794 super(delegate, mutex); 795 } 796 @Override protected ListMultimap<K, V> delegate() { 797 return (ListMultimap<K, V>) super.delegate(); 798 } 799 @Override public List<V> get(K key) { 800 synchronized (mutex) { 801 return list(delegate().get(key), mutex); 802 } 803 } 804 @Override public List<V> removeAll(Object key) { 805 synchronized (mutex) { 806 return delegate().removeAll(key); // copy not synchronized 807 } 808 } 809 @Override public List<V> replaceValues( 810 K key, Iterable<? extends V> values) { 811 synchronized (mutex) { 812 return delegate().replaceValues(key, values); // copy not synchronized 813 } 814 } 815 private static final long serialVersionUID = 0; 816 } 817 818 /** 819 * Returns a synchronized (thread-safe) set multimap backed by the specified 820 * multimap using the specified mutex. 821 * 822 * <p>You must follow the warnings described for {@link #multimap}. 823 * 824 * @param multimap the multimap to be wrapped in a synchronized view 825 * @return a synchronized view of the specified multimap 826 */ 827 public static <K, V> SetMultimap<K, V> setMultimap( 828 SetMultimap<K, V> multimap, @Nullable Object mutex) { 829 return new SynchronizedSetMultimap<K, V>(multimap, mutex); 830 } 831 832 /** @see Synchronized#setMultimap */ 833 private static class SynchronizedSetMultimap<K, V> 834 extends SynchronizedMultimap<K, V> implements SetMultimap<K, V> { 835 transient Set<Map.Entry<K, V>> entrySet; 836 SynchronizedSetMultimap( 837 SetMultimap<K, V> delegate, @Nullable Object mutex) { 838 super(delegate, mutex); 839 } 840 @Override protected SetMultimap<K, V> delegate() { 841 return (SetMultimap<K, V>) super.delegate(); 842 } 843 @Override public Set<V> get(K key) { 844 synchronized (mutex) { 845 return set(delegate().get(key), mutex); 846 } 847 } 848 @Override public Set<V> removeAll(Object key) { 849 synchronized (mutex) { 850 return delegate().removeAll(key); // copy not synchronized 851 } 852 } 853 @Override public Set<V> replaceValues( 854 K key, Iterable<? extends V> values) { 855 synchronized (mutex) { 856 return delegate().replaceValues(key, values); // copy not synchronized 857 } 858 } 859 @Override public Set<Map.Entry<K, V>> entries() { 860 synchronized (mutex) { 861 if (entrySet == null) { 862 entrySet = set(delegate().entries(), mutex); 863 } 864 return entrySet; 865 } 866 } 867 private static final long serialVersionUID = 0; 868 } 869 870 /** 871 * Returns a synchronized (thread-safe) sorted set multimap backed by the 872 * specified multimap using the specified mutex. 873 * 874 * <p>You must follow the warnings described for {@link #multimap}. 875 * 876 * @param multimap the multimap to be wrapped in a synchronized view 877 * @return a synchronized view of the specified multimap 878 */ 879 public static <K, V> SortedSetMultimap<K, V> sortedSetMultimap( 880 SortedSetMultimap<K, V> multimap, @Nullable Object mutex) { 881 return new SynchronizedSortedSetMultimap<K, V>(multimap, mutex); 882 } 883 884 /** @see Synchronized#sortedSetMultimap */ 885 private static class SynchronizedSortedSetMultimap<K, V> 886 extends SynchronizedSetMultimap<K, V> implements SortedSetMultimap<K, V> { 887 SynchronizedSortedSetMultimap( 888 SortedSetMultimap<K, V> delegate, @Nullable Object mutex) { 889 super(delegate, mutex); 890 } 891 @Override protected SortedSetMultimap<K, V> delegate() { 892 return (SortedSetMultimap<K, V>) super.delegate(); 893 } 894 @Override public SortedSet<V> get(K key) { 895 synchronized (mutex) { 896 return sortedSet(delegate().get(key), mutex); 897 } 898 } 899 @Override public SortedSet<V> removeAll(Object key) { 900 synchronized (mutex) { 901 return delegate().removeAll(key); // copy not synchronized 902 } 903 } 904 @Override public SortedSet<V> replaceValues( 905 K key, Iterable<? extends V> values) { 906 synchronized (mutex) { 907 return delegate().replaceValues(key, values); // copy not synchronized 908 } 909 } 910 public Comparator<? super V> valueComparator() { 911 synchronized (mutex) { 912 return delegate().valueComparator(); 913 } 914 } 915 private static final long serialVersionUID = 0; 916 } 917 918 /** 919 * Returns a synchronized (thread-safe) collection backed by the specified 920 * collection using the specified mutex. In order to guarantee serial access, 921 * it is critical that <b>all</b> access to the backing collection is 922 * accomplished through the returned collection. 923 * 924 * <p>It is imperative that the user manually synchronize on the specified 925 * mutex when iterating over the returned collection: <pre> {@code 926 * 927 * Collection<E> s = Synchronized.typePreservingCollection( 928 * new HashSet<E>(), mutex); 929 * ... 930 * synchronized (mutex) { 931 * Iterator<E> i = s.iterator(); // Must be in synchronized block 932 * while (i.hasNext()) { 933 * foo(i.next()); 934 * } 935 * }}</pre> 936 * 937 * Failure to follow this advice may result in non-deterministic behavior. 938 * 939 * <p>If the specified collection is a {@code SortedSet}, {@code Set} or 940 * {@code List}, this method will behave identically to {@link #sortedSet}, 941 * {@link #set} or {@link #list} respectively, in that order of specificity. 942 * 943 * @param collection the collection to be wrapped in a synchronized view 944 * @return a synchronized view of the specified collection 945 */ 946 private static <E> Collection<E> typePreservingCollection( 947 Collection<E> collection, @Nullable Object mutex) { 948 if (collection instanceof SortedSet) { 949 return sortedSet((SortedSet<E>) collection, mutex); 950 } else if (collection instanceof Set) { 951 return set((Set<E>) collection, mutex); 952 } else if (collection instanceof List) { 953 return list((List<E>) collection, mutex); 954 } else { 955 return collection(collection, mutex); 956 } 957 } 958 959 /** 960 * Returns a synchronized (thread-safe) set backed by the specified set using 961 * the specified mutex. In order to guarantee serial access, it is critical 962 * that <b>all</b> access to the backing collection is accomplished through 963 * the returned collection. 964 * 965 * <p>It is imperative that the user manually synchronize on the specified 966 * mutex when iterating over the returned collection: <pre> {@code 967 * 968 * Set<E> s = Synchronized.typePreservingSet( 969 * new HashSet<E>(), mutex); 970 * ... 971 * synchronized (mutex) { 972 * Iterator<E> i = s.iterator(); // Must be in synchronized block 973 * while (i.hasNext()) { 974 * foo(i.next()); 975 * } 976 * }}</pre> 977 * 978 * Failure to follow this advice may result in non-deterministic behavior. 979 * 980 * <p>If the specified collection is a {@code SortedSet} this method will 981 * behave identically to {@link #sortedSet}. 982 * 983 * @param set the set to be wrapped in a synchronized view 984 * @return a synchronized view of the specified set 985 */ 986 public static <E> Set<E> typePreservingSet( 987 Set<E> set, @Nullable Object mutex) { 988 if (set instanceof SortedSet) { 989 return sortedSet((SortedSet<E>) set, mutex); 990 } else { 991 return set(set, mutex); 992 } 993 } 994 995 /** @see Synchronized#multimap */ 996 static class SynchronizedAsMapEntries<K, V> 997 extends SynchronizedSet<Map.Entry<K, Collection<V>>> { 998 public SynchronizedAsMapEntries( 999 Set<Map.Entry<K, Collection<V>>> delegate, @Nullable Object mutex) { 1000 super(delegate, mutex); 1001 } 1002 1003 @Override public Iterator<Map.Entry<K, Collection<V>>> iterator() { 1004 // Must be manually synchronized. 1005 final Iterator<Map.Entry<K, Collection<V>>> iterator = super.iterator(); 1006 return new ForwardingIterator<Map.Entry<K, Collection<V>>>() { 1007 @Override protected Iterator<Map.Entry<K, Collection<V>>> delegate() { 1008 return iterator; 1009 } 1010 1011 @Override public Map.Entry<K, Collection<V>> next() { 1012 final Map.Entry<K, Collection<V>> entry = iterator.next(); 1013 return new ForwardingMapEntry<K, Collection<V>>() { 1014 @Override protected Map.Entry<K, Collection<V>> delegate() { 1015 return entry; 1016 } 1017 @Override public Collection<V> getValue() { 1018 return typePreservingCollection(entry.getValue(), mutex); 1019 } 1020 }; 1021 } 1022 }; 1023 } 1024 1025 // See Collections.CheckedMap.CheckedEntrySet for details on attacks. 1026 1027 @Override public Object[] toArray() { 1028 synchronized (mutex) { 1029 return ObjectArrays.toArrayImpl(delegate()); 1030 } 1031 } 1032 @Override public <T> T[] toArray(T[] array) { 1033 synchronized (mutex) { 1034 return ObjectArrays.toArrayImpl(delegate(), array); 1035 } 1036 } 1037 @Override public boolean contains(Object o) { 1038 synchronized (mutex) { 1039 return Maps.containsEntryImpl(delegate(), o); 1040 } 1041 } 1042 @Override public boolean containsAll(Collection<?> c) { 1043 synchronized (mutex) { 1044 return Collections2.containsAll(delegate(), c); 1045 } 1046 } 1047 @Override public boolean equals(Object o) { 1048 if (o == this) { 1049 return true; 1050 } 1051 synchronized (mutex) { 1052 return Collections2.setEquals(delegate(), o); 1053 } 1054 } 1055 @Override public boolean remove(Object o) { 1056 synchronized (mutex) { 1057 return Maps.removeEntryImpl(delegate(), o); 1058 } 1059 } 1060 @Override public boolean removeAll(Collection<?> c) { 1061 synchronized (mutex) { 1062 return Iterators.removeAll(delegate().iterator(), c); 1063 } 1064 } 1065 @Override public boolean retainAll(Collection<?> c) { 1066 synchronized (mutex) { 1067 return Iterators.retainAll(delegate().iterator(), c); 1068 } 1069 } 1070 1071 private static final long serialVersionUID = 0; 1072 } 1073 1074 /** 1075 * Returns a synchronized (thread-safe) map backed by the specified map using 1076 * the specified mutex. In order to guarantee serial access, it is critical 1077 * that <b>all</b> access to the backing map is accomplished through the 1078 * returned map. 1079 * 1080 * <p>It is imperative that the user manually synchronize on the specified 1081 * mutex when accessing any of the return map's collection views: 1082 * <pre> {@code 1083 * 1084 * Map<K, V> m = Synchronized.map( 1085 * new HashMap<K, V>(), mutex); 1086 * ... 1087 * Set<K> s = m.keySet(); // Needn't be in synchronized block 1088 * ... 1089 * synchronized (mutex) { 1090 * Iterator<K> i = s.iterator(); // Must be in synchronized block 1091 * while (i.hasNext()) { 1092 * foo(i.next()); 1093 * } 1094 * }}</pre> 1095 * 1096 * Failure to follow this advice may result in non-deterministic behavior. 1097 * 1098 * @param map the map to be wrapped in a synchronized view 1099 * @return a synchronized view of the specified map 1100 */ 1101 public static <K, V> Map<K, V> map(Map<K, V> map, @Nullable Object mutex) { 1102 return new SynchronizedMap<K, V>(map, mutex); 1103 } 1104 1105 /** @see Synchronized#map */ 1106 static class SynchronizedMap<K, V> extends SynchronizedObject 1107 implements Map<K, V> { 1108 private transient Set<K> keySet; 1109 private transient Collection<V> values; 1110 private transient Set<Map.Entry<K, V>> entrySet; 1111 1112 public SynchronizedMap(Map<K, V> delegate, @Nullable Object mutex) { 1113 super(delegate, mutex); 1114 } 1115 1116 @SuppressWarnings("unchecked") 1117 @Override protected Map<K, V> delegate() { 1118 return (Map<K, V>) super.delegate(); 1119 } 1120 1121 public void clear() { 1122 synchronized (mutex) { 1123 delegate().clear(); 1124 } 1125 } 1126 1127 public boolean containsKey(Object key) { 1128 synchronized (mutex) { 1129 return delegate().containsKey(key); 1130 } 1131 } 1132 1133 public boolean containsValue(Object value) { 1134 synchronized (mutex) { 1135 return delegate().containsValue(value); 1136 } 1137 } 1138 1139 public Set<Map.Entry<K, V>> entrySet() { 1140 synchronized (mutex) { 1141 if (entrySet == null) { 1142 entrySet = set(delegate().entrySet(), mutex); 1143 } 1144 return entrySet; 1145 } 1146 } 1147 1148 public V get(Object key) { 1149 synchronized (mutex) { 1150 return delegate().get(key); 1151 } 1152 } 1153 1154 public boolean isEmpty() { 1155 synchronized (mutex) { 1156 return delegate().isEmpty(); 1157 } 1158 } 1159 1160 public Set<K> keySet() { 1161 synchronized (mutex) { 1162 if (keySet == null) { 1163 keySet = set(delegate().keySet(), mutex); 1164 } 1165 return keySet; 1166 } 1167 } 1168 1169 public V put(K key, V value) { 1170 synchronized (mutex) { 1171 return delegate().put(key, value); 1172 } 1173 } 1174 1175 public void putAll(Map<? extends K, ? extends V> map) { 1176 synchronized (mutex) { 1177 delegate().putAll(map); 1178 } 1179 } 1180 1181 public V remove(Object key) { 1182 synchronized (mutex) { 1183 return delegate().remove(key); 1184 } 1185 } 1186 1187 public int size() { 1188 synchronized (mutex) { 1189 return delegate().size(); 1190 } 1191 } 1192 1193 public Collection<V> values() { 1194 synchronized (mutex) { 1195 if (values == null) { 1196 values = collection(delegate().values(), mutex); 1197 } 1198 return values; 1199 } 1200 } 1201 1202 @Override public boolean equals(Object o) { 1203 if (o == this) { 1204 return true; 1205 } 1206 synchronized (mutex) { 1207 return delegate().equals(o); 1208 } 1209 } 1210 1211 @Override public int hashCode() { 1212 synchronized (mutex) { 1213 return delegate().hashCode(); 1214 } 1215 } 1216 1217 private static final long serialVersionUID = 0; 1218 } 1219 1220 /** 1221 * Returns a synchronized (thread-safe) bimap backed by the specified bimap 1222 * using the specified mutex. In order to guarantee serial access, it is 1223 * critical that <b>all</b> access to the backing bimap is accomplished 1224 * through the returned bimap. 1225 * 1226 * <p>It is imperative that the user manually synchronize on the specified 1227 * mutex when accessing any of the return bimap's collection views: 1228 * <pre> {@code 1229 * 1230 * BiMap<K, V> m = Synchronized.biMap( 1231 * HashBiMap.<K, V>create(), mutex); 1232 * ... 1233 * Set<K> s = m.keySet(); // Needn't be in synchronized block 1234 * ... 1235 * synchronized (mutex) { 1236 * Iterator<K> i = s.iterator(); // Must be in synchronized block 1237 * while (i.hasNext()) { 1238 * foo(i.next()); 1239 * } 1240 * }}</pre> 1241 * 1242 * Failure to follow this advice may result in non-deterministic behavior. 1243 * 1244 * @param bimap the bimap to be wrapped in a synchronized view 1245 * @return a synchronized view of the specified bimap 1246 */ 1247 public static <K, V> BiMap<K, V> biMap( 1248 BiMap<K, V> bimap, @Nullable Object mutex) { 1249 return new SynchronizedBiMap<K, V>(bimap, mutex, null); 1250 } 1251 1252 /** @see Synchronized#biMap */ 1253 static class SynchronizedBiMap<K, V> extends SynchronizedMap<K, V> 1254 implements BiMap<K, V>, Serializable { 1255 private transient Set<V> valueSet; 1256 private transient BiMap<V, K> inverse; 1257 1258 public SynchronizedBiMap( 1259 BiMap<K, V> delegate, @Nullable Object mutex, 1260 @Nullable BiMap<V, K> inverse) { 1261 super(delegate, mutex); 1262 this.inverse = inverse; 1263 } 1264 1265 @Override protected BiMap<K, V> delegate() { 1266 return (BiMap<K, V>) super.delegate(); 1267 } 1268 1269 @Override public Set<V> values() { 1270 synchronized (mutex) { 1271 if (valueSet == null) { 1272 valueSet = set(delegate().values(), mutex); 1273 } 1274 return valueSet; 1275 } 1276 } 1277 1278 public V forcePut(K key, V value) { 1279 synchronized (mutex) { 1280 return delegate().forcePut(key, value); 1281 } 1282 } 1283 1284 public BiMap<V, K> inverse() { 1285 synchronized (mutex) { 1286 if (inverse == null) { 1287 inverse 1288 = new SynchronizedBiMap<V, K>(delegate().inverse(), mutex, this); 1289 } 1290 return inverse; 1291 } 1292 } 1293 1294 private static final long serialVersionUID = 0; 1295 } 1296 1297 /** @see SynchronizedMultimap#asMap */ 1298 static class SynchronizedAsMap<K, V> 1299 extends SynchronizedMap<K, Collection<V>> { 1300 private transient Set<Map.Entry<K, Collection<V>>> asMapEntrySet; 1301 private transient Collection<Collection<V>> asMapValues; 1302 1303 public SynchronizedAsMap( 1304 Map<K, Collection<V>> delegate, @Nullable Object mutex) { 1305 super(delegate, mutex); 1306 } 1307 1308 @Override public Collection<V> get(Object key) { 1309 synchronized (mutex) { 1310 Collection<V> collection = super.get(key); 1311 return (collection == null) ? null 1312 : typePreservingCollection(collection, mutex); 1313 } 1314 } 1315 1316 @Override public Set<Map.Entry<K, Collection<V>>> entrySet() { 1317 synchronized (mutex) { 1318 if (asMapEntrySet == null) { 1319 asMapEntrySet = new SynchronizedAsMapEntries<K, V>( 1320 delegate().entrySet(), mutex); 1321 } 1322 return asMapEntrySet; 1323 } 1324 } 1325 1326 @Override public Collection<Collection<V>> values() { 1327 synchronized (mutex) { 1328 if (asMapValues == null) { 1329 asMapValues 1330 = new SynchronizedAsMapValues<V>(delegate().values(), mutex); 1331 } 1332 return asMapValues; 1333 } 1334 } 1335 1336 @Override public boolean containsValue(Object o) { 1337 // values() and its contains() method are both synchronized. 1338 return values().contains(o); 1339 } 1340 1341 private static final long serialVersionUID = 0; 1342 } 1343 1344 /** @see SynchronizedMultimap#asMap */ 1345 static class SynchronizedAsMapValues<V> 1346 extends SynchronizedCollection<Collection<V>> { 1347 SynchronizedAsMapValues( 1348 Collection<Collection<V>> delegate, @Nullable Object mutex) { 1349 super(delegate, mutex); 1350 } 1351 1352 @Override public Iterator<Collection<V>> iterator() { 1353 // Must be manually synchronized. 1354 final Iterator<Collection<V>> iterator = super.iterator(); 1355 return new ForwardingIterator<Collection<V>>() { 1356 @Override protected Iterator<Collection<V>> delegate() { 1357 return iterator; 1358 } 1359 @Override public Collection<V> next() { 1360 return typePreservingCollection(iterator.next(), mutex); 1361 } 1362 }; 1363 } 1364 1365 private static final long serialVersionUID = 0; 1366 } 1367 } 1368