ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.1
Committed: Sat Mar 26 06:22:50 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

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