2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
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
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/
36 package java.util.concurrent;
38 import sun.misc.Unsafe;
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.
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.
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.
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.
77 * <p>This class is a member of the
78 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
79 * Java Collections Framework</a>.
82 * @param <E> the type of elements maintained by this set
85 public class ConcurrentSkipListSet<E>
86 extends AbstractSet<E>
87 implements NavigableSet<E>, Cloneable, java.io.Serializable {
89 private static final long serialVersionUID = -2479143111061671589L;
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()
96 private final ConcurrentNavigableMap<E,Object> m;
99 * Constructs a new, empty set that orders its elements according to
100 * their {@linkplain Comparable natural ordering}.
102 public ConcurrentSkipListSet() {
103 m = new ConcurrentSkipListMap<E,Object>();
107 * Constructs a new, empty set that orders its elements according to
108 * the specified comparator.
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.
114 public ConcurrentSkipListSet(Comparator<? super E> comparator) {
115 m = new ConcurrentSkipListMap<E,Object>(comparator);
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}.
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
129 public ConcurrentSkipListSet(Collection<? extends E> c) {
130 m = new ConcurrentSkipListMap<E,Object>();
135 * Constructs a new set containing the same elements and using the
136 * same ordering as the specified sorted set.
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
142 public ConcurrentSkipListSet(SortedSet<E> s) {
143 m = new ConcurrentSkipListMap<E,Object>(s.comparator());
150 ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
155 * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
156 * instance. (The elements themselves are not cloned.)
158 * @return a shallow copy of this set
160 public ConcurrentSkipListSet<E> clone() {
161 ConcurrentSkipListSet<E> clone = null;
163 clone = (ConcurrentSkipListSet<E>) super.clone();
164 clone.setMap(new ConcurrentSkipListMap(m));
165 } catch (CloneNotSupportedException e) {
166 throw new InternalError();
172 /* ---------------- Set operations -------------- */
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>.
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.
188 * @return the number of elements in this set
195 * Returns <tt>true</tt> if this set contains no elements.
196 * @return <tt>true</tt> if this set contains no elements
198 public boolean isEmpty() {
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>.
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
213 public boolean contains(Object o) {
214 return m.containsKey(o);
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>.
224 * @param e element to be added to this set
225 * @return <tt>true</tt> if this set did not already contain the
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
231 public boolean add(E e) {
232 return m.putIfAbsent(e, Boolean.TRUE) == null;
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.)
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
249 public boolean remove(Object o) {
250 return m.remove(o, Boolean.TRUE);
254 * Removes all of the elements from this set.
256 public void clear() {
261 * Returns an iterator over the elements in this set in ascending order.
263 * @return an iterator over the elements in this set in ascending order
265 public Iterator<E> iterator() {
266 return m.navigableKeySet().iterator();
270 * Returns an iterator over the elements in this set in descending order.
272 * @return an iterator over the elements in this set in descending order
274 public Iterator<E> descendingIterator() {
275 return m.descendingKeySet().iterator();
279 /* ---------------- AbstractSet Overrides -------------- */
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
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
293 public boolean equals(Object o) {
294 // Override AbstractSet version to avoid calling size()
297 if (!(o instanceof Set))
299 Collection<?> c = (Collection<?>) o;
301 return containsAll(c) && c.containsAll(this);
302 } catch (ClassCastException unused) {
304 } catch (NullPointerException unused) {
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.
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
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()))
331 /* ---------------- Relational operations -------------- */
334 * @throws ClassCastException {@inheritDoc}
335 * @throws NullPointerException if the specified element is null
337 public E lower(E e) {
338 return m.lowerKey(e);
342 * @throws ClassCastException {@inheritDoc}
343 * @throws NullPointerException if the specified element is null
345 public E floor(E e) {
346 return m.floorKey(e);
350 * @throws ClassCastException {@inheritDoc}
351 * @throws NullPointerException if the specified element is null
353 public E ceiling(E e) {
354 return m.ceilingKey(e);
358 * @throws ClassCastException {@inheritDoc}
359 * @throws NullPointerException if the specified element is null
361 public E higher(E e) {
362 return m.higherKey(e);
365 public E pollFirst() {
366 Map.Entry<E,Object> e = m.pollFirstEntry();
367 return (e == null) ? null : e.getKey();
370 public E pollLast() {
371 Map.Entry<E,Object> e = m.pollLastEntry();
372 return (e == null) ? null : e.getKey();
376 /* ---------------- SortedSet operations -------------- */
379 public Comparator<? super E> comparator() {
380 return m.comparator();
384 * @throws NoSuchElementException {@inheritDoc}
391 * @throws NoSuchElementException {@inheritDoc}
398 * @throws ClassCastException {@inheritDoc}
399 * @throws NullPointerException if {@code fromElement} or
400 * {@code toElement} is null
401 * @throws IllegalArgumentException {@inheritDoc}
403 public NavigableSet<E> subSet(E fromElement,
404 boolean fromInclusive,
406 boolean toInclusive) {
407 return new ConcurrentSkipListSet<E>
408 (m.subMap(fromElement, fromInclusive,
409 toElement, toInclusive));
413 * @throws ClassCastException {@inheritDoc}
414 * @throws NullPointerException if {@code toElement} is null
415 * @throws IllegalArgumentException {@inheritDoc}
417 public NavigableSet<E> headSet(E toElement, boolean inclusive) {
418 return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
422 * @throws ClassCastException {@inheritDoc}
423 * @throws NullPointerException if {@code fromElement} is null
424 * @throws IllegalArgumentException {@inheritDoc}
426 public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
427 return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
431 * @throws ClassCastException {@inheritDoc}
432 * @throws NullPointerException if {@code fromElement} or
433 * {@code toElement} is null
434 * @throws IllegalArgumentException {@inheritDoc}
436 public NavigableSet<E> subSet(E fromElement, E toElement) {
437 return subSet(fromElement, true, toElement, false);
441 * @throws ClassCastException {@inheritDoc}
442 * @throws NullPointerException if {@code toElement} is null
443 * @throws IllegalArgumentException {@inheritDoc}
445 public NavigableSet<E> headSet(E toElement) {
446 return headSet(toElement, false);
450 * @throws ClassCastException {@inheritDoc}
451 * @throws NullPointerException if {@code fromElement} is null
452 * @throws IllegalArgumentException {@inheritDoc}
454 public NavigableSet<E> tailSet(E fromElement) {
455 return tailSet(fromElement, true);
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.
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}.
468 * @return a reverse order view of this set
470 public NavigableSet<E> descendingSet() {
471 return new ConcurrentSkipListSet(m.descendingMap());
474 // Support for resetting map in clone
475 private void setMap(ConcurrentNavigableMap<E,Object> map) {
476 UNSAFE.putObjectVolatile(this, mapOffset, map);
479 private static final sun.misc.Unsafe UNSAFE;
480 private static final long mapOffset;
483 UNSAFE = sun.misc.Unsafe.getUnsafe();
484 Class k = ConcurrentSkipListSet.class;
485 mapOffset = UNSAFE.objectFieldOffset
486 (k.getDeclaredField("m"));
487 } catch (Exception e) {