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