Save This Page
Home » openjdk-7 » java » util » concurrent » [javadoc | source]
    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   }

Save This Page
Home » openjdk-7 » java » util » concurrent » [javadoc | source]