ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentSkipListSet.java
Revision: 1.23
Committed: Fri Apr 22 11:51:42 2011 UTC (13 years, 1 month ago) by dl
Branch: MAIN
CVS Tags: release-1_7_0
Changes since 1.22: +8 -6 lines
Log Message:
Improved bulk operation disclaimers for concurrent collections

File Contents

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