rt/emul/compact/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 19 Mar 2016 10:46:31 +0100
branchjdk7-b147
changeset 1890 212417b74b72
child 1895 bfaf3300b7ba
permissions -rw-r--r--
Bringing in all concurrent package from JDK7-b147
     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  *
     4  * This code is free software; you can redistribute it and/or modify it
     5  * under the terms of the GNU General Public License version 2 only, as
     6  * published by the Free Software Foundation.  Oracle designates this
     7  * particular file as subject to the "Classpath" exception as provided
     8  * by Oracle in the LICENSE file that accompanied this code.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  */
    24 
    25 /*
    26  * This file is available under and governed by the GNU General Public
    27  * License version 2 only, as published by the Free Software Foundation.
    28  * However, the following notice accompanied the original version of this
    29  * file:
    30  *
    31  * Written by Doug Lea with assistance from members of JCP JSR-166
    32  * Expert Group and released to the public domain, as explained at
    33  * http://creativecommons.org/publicdomain/zero/1.0/
    34  */
    35 
    36 package java.util.concurrent;
    37 import java.util.*;
    38 import sun.misc.Unsafe;
    39 
    40 /**
    41  * A scalable concurrent {@link NavigableSet} implementation based on
    42  * a {@link ConcurrentSkipListMap}.  The elements of the set are kept
    43  * sorted according to their {@linkplain Comparable natural ordering},
    44  * or by a {@link Comparator} provided at set creation time, depending
    45  * on which constructor is used.
    46  *
    47  * <p>This implementation provides expected average <i>log(n)</i> time
    48  * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
    49  * operations and their variants.  Insertion, removal, and access
    50  * operations safely execute concurrently by multiple threads.
    51  * Iterators are <i>weakly consistent</i>, returning elements
    52  * reflecting the state of the set at some point at or since the
    53  * creation of the iterator.  They do <em>not</em> throw {@link
    54  * ConcurrentModificationException}, and may proceed concurrently with
    55  * other operations.  Ascending ordered views and their iterators are
    56  * faster than descending ones.
    57  *
    58  * <p>Beware that, unlike in most collections, the <tt>size</tt>
    59  * method is <em>not</em> a constant-time operation. Because of the
    60  * asynchronous nature of these sets, determining the current number
    61  * of elements requires a traversal of the elements, and so may report
    62  * inaccurate results if this collection is modified during traversal.
    63  * Additionally, the bulk operations <tt>addAll</tt>,
    64  * <tt>removeAll</tt>, <tt>retainAll</tt>, <tt>containsAll</tt>,
    65  * <tt>equals</tt>, and <tt>toArray</tt> are <em>not</em> guaranteed
    66  * to be performed atomically. For example, an iterator operating
    67  * concurrently with an <tt>addAll</tt> operation might view only some
    68  * of the added elements.
    69  *
    70  * <p>This class and its iterators implement all of the
    71  * <em>optional</em> methods of the {@link Set} and {@link Iterator}
    72  * interfaces. Like most other concurrent collection implementations,
    73  * this class does not permit the use of <tt>null</tt> elements,
    74  * because <tt>null</tt> arguments and return values cannot be reliably
    75  * distinguished from the absence of elements.
    76  *
    77  * <p>This class is a member of the
    78  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    79  * Java Collections Framework</a>.
    80  *
    81  * @author Doug Lea
    82  * @param <E> the type of elements maintained by this set
    83  * @since 1.6
    84  */
    85 public class ConcurrentSkipListSet<E>
    86     extends AbstractSet<E>
    87     implements NavigableSet<E>, Cloneable, java.io.Serializable {
    88 
    89     private static final long serialVersionUID = -2479143111061671589L;
    90 
    91     /**
    92      * The underlying map. Uses Boolean.TRUE as value for each
    93      * element.  This field is declared final for the sake of thread
    94      * safety, which entails some ugliness in clone()
    95      */
    96     private final ConcurrentNavigableMap<E,Object> m;
    97 
    98     /**
    99      * Constructs a new, empty set that orders its elements according to
   100      * their {@linkplain Comparable natural ordering}.
   101      */
   102     public ConcurrentSkipListSet() {
   103         m = new ConcurrentSkipListMap<E,Object>();
   104     }
   105 
   106     /**
   107      * Constructs a new, empty set that orders its elements according to
   108      * the specified comparator.
   109      *
   110      * @param comparator the comparator that will be used to order this set.
   111      *        If <tt>null</tt>, the {@linkplain Comparable natural
   112      *        ordering} of the elements will be used.
   113      */
   114     public ConcurrentSkipListSet(Comparator<? super E> comparator) {
   115         m = new ConcurrentSkipListMap<E,Object>(comparator);
   116     }
   117 
   118     /**
   119      * Constructs a new set containing the elements in the specified
   120      * collection, that orders its elements according to their
   121      * {@linkplain Comparable natural ordering}.
   122      *
   123      * @param c The elements that will comprise the new set
   124      * @throws ClassCastException if the elements in <tt>c</tt> are
   125      *         not {@link Comparable}, or are not mutually comparable
   126      * @throws NullPointerException if the specified collection or any
   127      *         of its elements are null
   128      */
   129     public ConcurrentSkipListSet(Collection<? extends E> c) {
   130         m = new ConcurrentSkipListMap<E,Object>();
   131         addAll(c);
   132     }
   133 
   134     /**
   135      * Constructs a new set containing the same elements and using the
   136      * same ordering as the specified sorted set.
   137      *
   138      * @param s sorted set whose elements will comprise the new set
   139      * @throws NullPointerException if the specified sorted set or any
   140      *         of its elements are null
   141      */
   142     public ConcurrentSkipListSet(SortedSet<E> s) {
   143         m = new ConcurrentSkipListMap<E,Object>(s.comparator());
   144         addAll(s);
   145     }
   146 
   147     /**
   148      * For use by submaps
   149      */
   150     ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
   151         this.m = m;
   152     }
   153 
   154     /**
   155      * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
   156      * instance. (The elements themselves are not cloned.)
   157      *
   158      * @return a shallow copy of this set
   159      */
   160     public ConcurrentSkipListSet<E> clone() {
   161         ConcurrentSkipListSet<E> clone = null;
   162         try {
   163             clone = (ConcurrentSkipListSet<E>) super.clone();
   164             clone.setMap(new ConcurrentSkipListMap(m));
   165         } catch (CloneNotSupportedException e) {
   166             throw new InternalError();
   167         }
   168 
   169         return clone;
   170     }
   171 
   172     /* ---------------- Set operations -------------- */
   173 
   174     /**
   175      * Returns the number of elements in this set.  If this set
   176      * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
   177      * returns <tt>Integer.MAX_VALUE</tt>.
   178      *
   179      * <p>Beware that, unlike in most collections, this method is
   180      * <em>NOT</em> a constant-time operation. Because of the
   181      * asynchronous nature of these sets, determining the current
   182      * number of elements requires traversing them all to count them.
   183      * Additionally, it is possible for the size to change during
   184      * execution of this method, in which case the returned result
   185      * will be inaccurate. Thus, this method is typically not very
   186      * useful in concurrent applications.
   187      *
   188      * @return the number of elements in this set
   189      */
   190     public int size() {
   191         return m.size();
   192     }
   193 
   194     /**
   195      * Returns <tt>true</tt> if this set contains no elements.
   196      * @return <tt>true</tt> if this set contains no elements
   197      */
   198     public boolean isEmpty() {
   199         return m.isEmpty();
   200     }
   201 
   202     /**
   203      * Returns <tt>true</tt> if this set contains the specified element.
   204      * More formally, returns <tt>true</tt> if and only if this set
   205      * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
   206      *
   207      * @param o object to be checked for containment in this set
   208      * @return <tt>true</tt> if this set contains the specified element
   209      * @throws ClassCastException if the specified element cannot be
   210      *         compared with the elements currently in this set
   211      * @throws NullPointerException if the specified element is null
   212      */
   213     public boolean contains(Object o) {
   214         return m.containsKey(o);
   215     }
   216 
   217     /**
   218      * Adds the specified element to this set if it is not already present.
   219      * More formally, adds the specified element <tt>e</tt> to this set if
   220      * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
   221      * If this set already contains the element, the call leaves the set
   222      * unchanged and returns <tt>false</tt>.
   223      *
   224      * @param e element to be added to this set
   225      * @return <tt>true</tt> if this set did not already contain the
   226      *         specified element
   227      * @throws ClassCastException if <tt>e</tt> cannot be compared
   228      *         with the elements currently in this set
   229      * @throws NullPointerException if the specified element is null
   230      */
   231     public boolean add(E e) {
   232         return m.putIfAbsent(e, Boolean.TRUE) == null;
   233     }
   234 
   235     /**
   236      * Removes the specified element from this set if it is present.
   237      * More formally, removes an element <tt>e</tt> such that
   238      * <tt>o.equals(e)</tt>, if this set contains such an element.
   239      * Returns <tt>true</tt> if this set contained the element (or
   240      * equivalently, if this set changed as a result of the call).
   241      * (This set will not contain the element once the call returns.)
   242      *
   243      * @param o object to be removed from this set, if present
   244      * @return <tt>true</tt> if this set contained the specified element
   245      * @throws ClassCastException if <tt>o</tt> cannot be compared
   246      *         with the elements currently in this set
   247      * @throws NullPointerException if the specified element is null
   248      */
   249     public boolean remove(Object o) {
   250         return m.remove(o, Boolean.TRUE);
   251     }
   252 
   253     /**
   254      * Removes all of the elements from this set.
   255      */
   256     public void clear() {
   257         m.clear();
   258     }
   259 
   260     /**
   261      * Returns an iterator over the elements in this set in ascending order.
   262      *
   263      * @return an iterator over the elements in this set in ascending order
   264      */
   265     public Iterator<E> iterator() {
   266         return m.navigableKeySet().iterator();
   267     }
   268 
   269     /**
   270      * Returns an iterator over the elements in this set in descending order.
   271      *
   272      * @return an iterator over the elements in this set in descending order
   273      */
   274     public Iterator<E> descendingIterator() {
   275         return m.descendingKeySet().iterator();
   276     }
   277 
   278 
   279     /* ---------------- AbstractSet Overrides -------------- */
   280 
   281     /**
   282      * Compares the specified object with this set for equality.  Returns
   283      * <tt>true</tt> if the specified object is also a set, the two sets
   284      * have the same size, and every member of the specified set is
   285      * contained in this set (or equivalently, every member of this set is
   286      * contained in the specified set).  This definition ensures that the
   287      * equals method works properly across different implementations of the
   288      * set interface.
   289      *
   290      * @param o the object to be compared for equality with this set
   291      * @return <tt>true</tt> if the specified object is equal to this set
   292      */
   293     public boolean equals(Object o) {
   294         // Override AbstractSet version to avoid calling size()
   295         if (o == this)
   296             return true;
   297         if (!(o instanceof Set))
   298             return false;
   299         Collection<?> c = (Collection<?>) o;
   300         try {
   301             return containsAll(c) && c.containsAll(this);
   302         } catch (ClassCastException unused)   {
   303             return false;
   304         } catch (NullPointerException unused) {
   305             return false;
   306         }
   307     }
   308 
   309     /**
   310      * Removes from this set all of its elements that are contained in
   311      * the specified collection.  If the specified collection is also
   312      * a set, this operation effectively modifies this set so that its
   313      * value is the <i>asymmetric set difference</i> of the two sets.
   314      *
   315      * @param  c collection containing elements to be removed from this set
   316      * @return <tt>true</tt> if this set changed as a result of the call
   317      * @throws ClassCastException if the types of one or more elements in this
   318      *         set are incompatible with the specified collection
   319      * @throws NullPointerException if the specified collection or any
   320      *         of its elements are null
   321      */
   322     public boolean removeAll(Collection<?> c) {
   323         // Override AbstractSet version to avoid unnecessary call to size()
   324         boolean modified = false;
   325         for (Iterator<?> i = c.iterator(); i.hasNext(); )
   326             if (remove(i.next()))
   327                 modified = true;
   328         return modified;
   329     }
   330 
   331     /* ---------------- Relational operations -------------- */
   332 
   333     /**
   334      * @throws ClassCastException {@inheritDoc}
   335      * @throws NullPointerException if the specified element is null
   336      */
   337     public E lower(E e) {
   338         return m.lowerKey(e);
   339     }
   340 
   341     /**
   342      * @throws ClassCastException {@inheritDoc}
   343      * @throws NullPointerException if the specified element is null
   344      */
   345     public E floor(E e) {
   346         return m.floorKey(e);
   347     }
   348 
   349     /**
   350      * @throws ClassCastException {@inheritDoc}
   351      * @throws NullPointerException if the specified element is null
   352      */
   353     public E ceiling(E e) {
   354         return m.ceilingKey(e);
   355     }
   356 
   357     /**
   358      * @throws ClassCastException {@inheritDoc}
   359      * @throws NullPointerException if the specified element is null
   360      */
   361     public E higher(E e) {
   362         return m.higherKey(e);
   363     }
   364 
   365     public E pollFirst() {
   366         Map.Entry<E,Object> e = m.pollFirstEntry();
   367         return (e == null) ? null : e.getKey();
   368     }
   369 
   370     public E pollLast() {
   371         Map.Entry<E,Object> e = m.pollLastEntry();
   372         return (e == null) ? null : e.getKey();
   373     }
   374 
   375 
   376     /* ---------------- SortedSet operations -------------- */
   377 
   378 
   379     public Comparator<? super E> comparator() {
   380         return m.comparator();
   381     }
   382 
   383     /**
   384      * @throws NoSuchElementException {@inheritDoc}
   385      */
   386     public E first() {
   387         return m.firstKey();
   388     }
   389 
   390     /**
   391      * @throws NoSuchElementException {@inheritDoc}
   392      */
   393     public E last() {
   394         return m.lastKey();
   395     }
   396 
   397     /**
   398      * @throws ClassCastException {@inheritDoc}
   399      * @throws NullPointerException if {@code fromElement} or
   400      *         {@code toElement} is null
   401      * @throws IllegalArgumentException {@inheritDoc}
   402      */
   403     public NavigableSet<E> subSet(E fromElement,
   404                                   boolean fromInclusive,
   405                                   E toElement,
   406                                   boolean toInclusive) {
   407         return new ConcurrentSkipListSet<E>
   408             (m.subMap(fromElement, fromInclusive,
   409                       toElement,   toInclusive));
   410     }
   411 
   412     /**
   413      * @throws ClassCastException {@inheritDoc}
   414      * @throws NullPointerException if {@code toElement} is null
   415      * @throws IllegalArgumentException {@inheritDoc}
   416      */
   417     public NavigableSet<E> headSet(E toElement, boolean inclusive) {
   418         return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
   419     }
   420 
   421     /**
   422      * @throws ClassCastException {@inheritDoc}
   423      * @throws NullPointerException if {@code fromElement} is null
   424      * @throws IllegalArgumentException {@inheritDoc}
   425      */
   426     public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
   427         return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
   428     }
   429 
   430     /**
   431      * @throws ClassCastException {@inheritDoc}
   432      * @throws NullPointerException if {@code fromElement} or
   433      *         {@code toElement} is null
   434      * @throws IllegalArgumentException {@inheritDoc}
   435      */
   436     public NavigableSet<E> subSet(E fromElement, E toElement) {
   437         return subSet(fromElement, true, toElement, false);
   438     }
   439 
   440     /**
   441      * @throws ClassCastException {@inheritDoc}
   442      * @throws NullPointerException if {@code toElement} is null
   443      * @throws IllegalArgumentException {@inheritDoc}
   444      */
   445     public NavigableSet<E> headSet(E toElement) {
   446         return headSet(toElement, false);
   447     }
   448 
   449     /**
   450      * @throws ClassCastException {@inheritDoc}
   451      * @throws NullPointerException if {@code fromElement} is null
   452      * @throws IllegalArgumentException {@inheritDoc}
   453      */
   454     public NavigableSet<E> tailSet(E fromElement) {
   455         return tailSet(fromElement, true);
   456     }
   457 
   458     /**
   459      * Returns a reverse order view of the elements contained in this set.
   460      * The descending set is backed by this set, so changes to the set are
   461      * reflected in the descending set, and vice-versa.
   462      *
   463      * <p>The returned set has an ordering equivalent to
   464      * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
   465      * The expression {@code s.descendingSet().descendingSet()} returns a
   466      * view of {@code s} essentially equivalent to {@code s}.
   467      *
   468      * @return a reverse order view of this set
   469      */
   470     public NavigableSet<E> descendingSet() {
   471         return new ConcurrentSkipListSet(m.descendingMap());
   472     }
   473 
   474     // Support for resetting map in clone
   475     private void setMap(ConcurrentNavigableMap<E,Object> map) {
   476         UNSAFE.putObjectVolatile(this, mapOffset, map);
   477     }
   478 
   479     private static final sun.misc.Unsafe UNSAFE;
   480     private static final long mapOffset;
   481     static {
   482         try {
   483             UNSAFE = sun.misc.Unsafe.getUnsafe();
   484             Class k = ConcurrentSkipListSet.class;
   485             mapOffset = UNSAFE.objectFieldOffset
   486                 (k.getDeclaredField("m"));
   487         } catch (Exception e) {
   488             throw new Error(e);
   489         }
   490     }
   491 }