ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166x/ConcurrentSkipListMap.java
Revision: 1.3
Committed: Tue Sep 7 11:37:57 2004 UTC (19 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.2: +45 -45 lines
Log Message:
Javadoc improvements

File Contents

# Content
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/licenses/publicdomain
5 */
6
7 package jsr166x;
8
9 import java.util.*;
10 import java.util.concurrent.*;
11 import java.util.concurrent.atomic.*;
12
13 /**
14 * A scalable {@link ConcurrentNavigableMap} implementation. This
15 * class maintains a map in ascending key order, sorted according to
16 * the <i>natural order</i> for the key's class (see {@link
17 * Comparable}), or by the {@link Comparator} provided at creation
18 * time, depending on which constructor is used.
19 *
20 * <p>This class implements a concurrent variant of <a
21 * href="http://www.cs.umd.edu/~pugh/">SkipLists</a> providing
22 * expected average <i>log(n)</i> time cost for the
23 * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and
24 * <tt>remove</tt> operations and their variants. Insertion, removal,
25 * update, and access operations safely execute concurrently by
26 * multiple threads. Iterators are <i>weakly consistent</i>, returning
27 * elements reflecting the state of the map at some point at or since
28 * the creation of the iterator. They do <em>not</em> throw {@link
29 * ConcurrentModificationException}, and may proceed concurrently with
30 * other operations.
31 *
32 * <p> All <tt>Map.Entry</tt> pairs returned by methods in this class
33 * and its views represent snapshots of mappings at the time they were
34 * produced. They do <em>not</em> support the <tt>Entry.setValue</tt>
35 * method. (Note however that it is possible to change mappings in the
36 * associated map using <tt>put</tt>, <tt>putIfAbsent</tt>, or
37 * <tt>replace</tt>, depending on exactly which effect you need.)
38 *
39 * <p>Beware that, unlike in most collections, the <tt>size</tt>
40 * method is <em>not</em> a constant-time operation. Because of the
41 * asynchronous nature of these maps, determining the current number
42 * of elements requires a traversal of the elements.
43 *
44 * <p>This class and its views and iterators implement all of the
45 * <em>optional</em> methods of the {@link Map} and {@link Iterator}
46 * interfaces. Like most other concurrent collections, this class does
47 * not permit the use of <tt>null</tt> keys or values because some
48 * null return values cannot be reliably distinguished from the
49 * absence of elements.
50 *
51 * @author Doug Lea
52 * @param <K> the type of keys maintained by this map
53 * @param <V> the type of mapped values
54 */
55 public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
56 implements ConcurrentNavigableMap<K,V>,
57 Cloneable,
58 java.io.Serializable {
59 /*
60 * This class implements a tree-like two-dimensionally linked skip
61 * list in which the index levels are represented in separate
62 * nodes from the base nodes holding data. There are two reasons
63 * for taking this approach instead of the usual array-based
64 * structure: 1) Array based implementations seem to encounter
65 * more complexity and overhead 2) We can use cheaper algorithms
66 * for the heavily-traversed index lists than can be used for the
67 * base lists. Here's a picture of some of the basics for a
68 * possible list with 2 levels of index:
69 *
70 * Head nodes Index nodes
71 * +-+ right +-+ +-+
72 * |2|---------------->| |--------------------->| |->null
73 * +-+ +-+ +-+
74 * | down | |
75 * v v v
76 * +-+ +-+ +-+ +-+ +-+ +-+
77 * |1|----------->| |->| |------>| |----------->| |------>| |->null
78 * +-+ +-+ +-+ +-+ +-+ +-+
79 * | | | | | |
80 * v Nodes v v v v v
81 * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
82 * | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null
83 * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
84 *
85 * The base lists use a variant of the HM linked ordered set
86 * algorithm (See Tim Harris, "A pragmatic implementation of
87 * non-blocking linked lists"
88 * http://www.cl.cam.ac.uk/~tlh20/publications.html and Maged
89 * Michael "High Performance Dynamic Lock-Free Hash Tables and
90 * List-Based Sets"
91 * http://www.research.ibm.com/people/m/michael/pubs.htm). The
92 * basic idea in these lists is to mark pointers of deleted nodes
93 * when deleting, and when traversing to keep track of triples
94 * (predecessor, node, successor) in order to detect when and how
95 * to unlink these deleted nodes.
96 *
97 * Rather than using mark-bits to mark list deletions (which can
98 * be slow and space-intensive using AtomicMarkedReference), nodes
99 * use direct CAS'able next pointers. On deletion, instead of
100 * marking a pointer, they splice in another node that can be
101 * thought of as standing for a marked pointer (indicating this by
102 * using otherwise impossible field values). Using plain nodes
103 * acts roughly like "boxed" implementations of marked pointers,
104 * but uses new nodes only when nodes are deleted, not for every
105 * link. This requires less space and supports faster
106 * traversal. Even if marked references were better supported by
107 * JVMs, traversal using this technique might still be faster
108 * because any search need only read ahead one more node than
109 * otherwise required (to check for trailing marker) rather than
110 * unmasking mark bits or whatever on each read.
111 *
112 * This approach maintains the essential property needed in the HM
113 * algorithm of changing the next-pointer of a deleted node so
114 * that any other CAS of it will fail, but implements the idea by
115 * changing the pointer to point to a different node, not by
116 * marking it. While it would be possible to further squeeze
117 * space by defining marker nodes not to have key/value fields, it
118 * isn't worth the extra type-testing overhead. The deletion
119 * markers are rarely encountered during traversal and are
120 * normally quickly garbage collected. (Note that this technique
121 * would not work well in systems without garbage collection.)
122 *
123 * In addition to using deletion markers, the lists also use
124 * nullness of value fields to indicate deletion, in a style
125 * similar to typical lazy-deletion schemes. If a node's value is
126 * null, then it is considered logically deleted and ignored even
127 * though it is still reachable. This maintains proper control of
128 * concurrent replace vs delete operations -- an attempted replace
129 * must fail if a delete beat it by nulling field, and a delete
130 * must return the last non-null value held in the field. (Note:
131 * Null, rather than some special marker, is used for value fields
132 * here because it just so happens to mesh with the Map API
133 * requirement that method get returns null if there is no
134 * mapping, which allows nodes to remain concurrently readable
135 * even when deleted. Using any other marker value here would be
136 * messy at best.)
137 *
138 * Here's the sequence of events for a deletion of node n with
139 * predecessor b and successor f, initially:
140 *
141 * +------+ +------+ +------+
142 * ... | b |------>| n |----->| f | ...
143 * +------+ +------+ +------+
144 *
145 * 1. CAS n's value field from non-null to null.
146 * From this point on, no public operations encountering
147 * the node consider this mapping to exist. However, other
148 * ongoing insertions and deletions might still modify
149 * n's next pointer.
150 *
151 * 2. CAS n's next pointer to point to a new marker node.
152 * From this point on, no other nodes can be appended to n.
153 * which avoids deletion errors in CAS-based linked lists.
154 *
155 * +------+ +------+ +------+ +------+
156 * ... | b |------>| n |----->|marker|------>| f | ...
157 * +------+ +------+ +------+ +------+
158 *
159 * 3. CAS b's next pointer over both n and its marker.
160 * From this point on, no new traversals will encounter n,
161 * and it can eventually be GCed.
162 * +------+ +------+
163 * ... | b |----------------------------------->| f | ...
164 * +------+ +------+
165 *
166 * A failure at step 1 leads to simple retry due to a lost race
167 * with another operation. Steps 2-3 can fail because some other
168 * thread noticed during a traversal a node with null value and
169 * helped out by marking and/or unlinking. This helping-out
170 * ensures that no thread can become stuck waiting for progress of
171 * the deleting thread. The use of marker nodes slightly
172 * complicates helping-out code because traversals must track
173 * consistent reads of up to four nodes (b, n, marker, f), not
174 * just (b, n, f), although the next field of a marker is
175 * immutable, and once a next field is CAS'ed to point to a
176 * marker, it never again changes, so this requires less care.
177 *
178 * Skip lists add indexing to this scheme, so that the base-level
179 * traversals start close to the locations being found, inserted
180 * or deleted -- usually base level traversals only traverse a few
181 * nodes. This doesn't change the basic algorithm except for the
182 * need to make sure base traversals start at predecessors (here,
183 * b) that are not (structurally) deleted, otherwise retrying
184 * after processing the deletion.
185 *
186 * Index levels are maintained as lists with volatile next fields,
187 * using CAS to link and unlink. Races are allowed in index-list
188 * operations that can (rarely) fail to link in a new index node
189 * or delete one. (We can't do this of course for data nodes.)
190 * However, even when this happens, the index lists remain sorted,
191 * so correctly serve as indices. This can impact performance,
192 * but since skip lists are probabilistic anyway, the net result
193 * is that under contention, the effective "p" value may be lower
194 * than its nominal value. And race windows are kept small enough
195 * that in practice these failures are rare, even under a lot of
196 * contention.
197 *
198 * The fact that retries (for both base and index lists) are
199 * relatively cheap due to indexing allows some minor
200 * simplifications of retry logic. Traversal restarts are
201 * performed after most "helping-out" CASes. This isn't always
202 * strictly necessary, but the implicit backoffs tend to help
203 * reduce other downstream failed CAS's enough to outweigh restart
204 * cost. This worsens the worst case, but seems to improve even
205 * highly contended cases.
206 *
207 * Unlike most skip-list implementations, index insertion and
208 * deletion here require a separate traversal pass occuring after
209 * the base-level action, to add or remove index nodes. This adds
210 * to single-threaded overhead, but improves contended
211 * multithreaded performance by narrowing interference windows,
212 * and allows deletion to ensure that all index nodes will be made
213 * unreachable upon return from a public remove operation, thus
214 * avoiding unwanted garbage retention. This is more important
215 * here than in some other data structures because we cannot null
216 * out node fields referencing user keys since they might still be
217 * read by other ongoing traversals.
218 *
219 * Indexing uses skip list parameters that maintain good search
220 * performance while using sparser-than-usual indices: The
221 * hardwired parameters k=1, p=0.5 (see method randomLevel) mean
222 * that about one-quarter of the nodes have indices. Of those that
223 * do, half have one level, a quarter have two, and so on (see
224 * Pugh's Skip List Cookbook, sec 3.4). The expected total space
225 * requirement for a map is slightly less than for the current
226 * implementation of java.util.TreeMap.
227 *
228 * Changing the level of the index (i.e, the height of the
229 * tree-like structure) also uses CAS. The head index has initial
230 * level/height of one. Creation of an index with height greater
231 * than the current level adds a level to the head index by
232 * CAS'ing on a new top-most head. To maintain good performance
233 * after a lot of removals, deletion methods heuristically try to
234 * reduce the height if the topmost levels appear to be empty.
235 * This may encounter races in which it possible (but rare) to
236 * reduce and "lose" a level just as it is about to contain an
237 * index (that will then never be encountered). This does no
238 * structural harm, and in practice appears to be a better option
239 * than allowing unrestrained growth of levels.
240 *
241 * The code for all this is more verbose than you'd like. Most
242 * operations entail locating an element (or position to insert an
243 * element). The code to do this can't be nicely factored out
244 * because subsequent uses require a snapshot of predecessor
245 * and/or successor and/or value fields which can't be returned
246 * all at once, at least not without creating yet another object
247 * to hold them -- creating such little objects is an especially
248 * bad idea for basic internal search operations because it adds
249 * to GC overhead. (This is one of the few times I've wished Java
250 * had macros.) Instead, some traversal code is interleaved within
251 * insertion and removal operations. The control logic to handle
252 * all the retry conditions is sometimes twisty. Most search is
253 * broken into 2 parts. findPredecessor() searches index nodes
254 * only, returning a base-level predecessor of the key. findNode()
255 * finishes out the base-level search. Even with this factoring,
256 * there is a fair amount of near-duplication of code to handle
257 * variants.
258 *
259 * For explanation of algorithms sharing at least a couple of
260 * features with this one, see Mikhail Fomitchev's thesis
261 * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
262 * (http://www.cl.cam.ac.uk/users/kaf24/), and papers by
263 * Håkan Sundell (http://www.cs.chalmers.se/~phs/).
264 *
265 * Given the use of tree-like index nodes, you might wonder why
266 * this doesn't use some kind of search tree instead, which would
267 * support somewhat faster search operations. The reason is that
268 * there are no known efficient lock-free insertion and deletion
269 * algorithms for search trees. The immutability of the "down"
270 * links of index nodes (as opposed to mutable "left" fields in
271 * true trees) makes this tractable using only CAS operations.
272 *
273 * Notation guide for local variables
274 * Node: b, n, f for predecessor, node, successor
275 * Index: q, r, d for index node, right, down.
276 * t for another index node
277 * Head: h
278 * Levels: j
279 * Keys: k, key
280 * Values: v, value
281 * Comparisons: c
282 */
283
284 private static final long serialVersionUID = -8627078645895051609L;
285
286 /**
287 * Special value used to identify base-level header
288 */
289 private static final Object BASE_HEADER = new Object();
290
291 /**
292 * The topmost head index of the skiplist.
293 */
294 private transient volatile HeadIndex<K,V> head;
295
296 /**
297 * The Comparator used to maintain order in this Map, or null
298 * if using natural order.
299 * @serial
300 */
301 private final Comparator<? super K> comparator;
302
303 /**
304 * Seed for simple random number generator. Not volatile since it
305 * doesn't matter too much if different threads don't see updates.
306 */
307 private transient int randomSeed;
308
309 /** Lazily initialized key set */
310 private transient KeySet keySet;
311 /** Lazily initialized entry set */
312 private transient EntrySet entrySet;
313 /** Lazily initialized values collection */
314 private transient Values values;
315
316 /**
317 * Initialize or reset state. Needed by constructors, clone,
318 * clear, readObject. and ConcurrentSkipListSet.clone.
319 * (Note that comparator must be separately initialized.)
320 */
321 final void initialize() {
322 keySet = null;
323 entrySet = null;
324 values = null;
325 randomSeed = (int) System.nanoTime();
326 head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
327 null, null, 1);
328 }
329
330 /** Updater for casHead */
331 private static final
332 AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex>
333 headUpdater = AtomicReferenceFieldUpdater.newUpdater
334 (ConcurrentSkipListMap.class, HeadIndex.class, "head");
335
336 /**
337 * compareAndSet head node
338 */
339 private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
340 return headUpdater.compareAndSet(this, cmp, val);
341 }
342
343 /* ---------------- Nodes -------------- */
344
345 /**
346 * Nodes hold keys and values, and are singly linked in sorted
347 * order, possibly with some intervening marker nodes. The list is
348 * headed by a dummy node accessible as head.node. The value field
349 * is declared only as Object because it takes special non-V
350 * values for marker and header nodes.
351 */
352 static final class Node<K,V> {
353 final K key;
354 volatile Object value;
355 volatile Node<K,V> next;
356
357 /**
358 * Creates a new regular node.
359 */
360 Node(K key, Object value, Node<K,V> next) {
361 this.key = key;
362 this.value = value;
363 this.next = next;
364 }
365
366 /**
367 * Creates a new marker node. A marker is distinguished by
368 * having its value field point to itself. Marker nodes also
369 * have null keys, a fact that is exploited in a few places,
370 * but this doesn't distinguish markers from the base-level
371 * header node (head.node), which also has a null key.
372 */
373 Node(Node<K,V> next) {
374 this.key = null;
375 this.value = this;
376 this.next = next;
377 }
378
379 /** Updater for casNext */
380 static final AtomicReferenceFieldUpdater<Node, Node>
381 nextUpdater = AtomicReferenceFieldUpdater.newUpdater
382 (Node.class, Node.class, "next");
383
384 /** Updater for casValue */
385 static final AtomicReferenceFieldUpdater<Node, Object>
386 valueUpdater = AtomicReferenceFieldUpdater.newUpdater
387 (Node.class, Object.class, "value");
388
389
390 /**
391 * compareAndSet value field
392 */
393 boolean casValue(Object cmp, Object val) {
394 return valueUpdater.compareAndSet(this, cmp, val);
395 }
396
397 /**
398 * compareAndSet next field
399 */
400 boolean casNext(Node<K,V> cmp, Node<K,V> val) {
401 return nextUpdater.compareAndSet(this, cmp, val);
402 }
403
404 /**
405 * Return true if this node is a marker. This method isn't
406 * actually called in an any current code checking for markers
407 * because callers will have already read value field and need
408 * to use that read (not another done here) and so directly
409 * test if value points to node.
410 * @param n a possibly null reference to a node
411 * @return true if this node is a marker node
412 */
413 boolean isMarker() {
414 return value == this;
415 }
416
417 /**
418 * Return true if this node is the header of base-level list.
419 * @return true if this node is header node
420 */
421 boolean isBaseHeader() {
422 return value == BASE_HEADER;
423 }
424
425 /**
426 * Tries to append a deletion marker to this node.
427 * @param f the assumed current successor of this node
428 * @return true if successful
429 */
430 boolean appendMarker(Node<K,V> f) {
431 return casNext(f, new Node<K,V>(f));
432 }
433
434 /**
435 * Helps out a deletion by appending marker or unlinking from
436 * predecessor. This is called during traversals when value
437 * field seen to be null.
438 * @param b predecessor
439 * @param f successor
440 */
441 void helpDelete(Node<K,V> b, Node<K,V> f) {
442 /*
443 * Rechecking links and then doing only one of the
444 * help-out stages per call tends to minimize CAS
445 * interference among helping threads.
446 */
447 if (f == next && this == b.next) {
448 if (f == null || f.value != f) // not already marked
449 appendMarker(f);
450 else
451 b.casNext(this, f.next);
452 }
453 }
454
455 /**
456 * Return value if this node contains a valid key-value pair,
457 * else null.
458 * @return this node's value if it isn't a marker or header or
459 * is deleted, else null.
460 */
461 V getValidValue() {
462 Object v = value;
463 if (v == this || v == BASE_HEADER)
464 return null;
465 return (V)v;
466 }
467
468 /**
469 * Create and return a new SnapshotEntry holding current
470 * mapping if this node holds a valid value, else null
471 * @return new entry or null
472 */
473 SnapshotEntry<K,V> createSnapshot() {
474 V v = getValidValue();
475 if (v == null)
476 return null;
477 return new SnapshotEntry(key, v);
478 }
479 }
480
481 /* ---------------- Indexing -------------- */
482
483 /**
484 * Index nodes represent the levels of the skip list. To improve
485 * search performance, keys of the underlying nodes are cached.
486 * Note that even though both Nodes and Indexes have
487 * forward-pointing fields, they have different types and are
488 * handled in different ways, that can't nicely be captured by
489 * placing field in a shared abstract class.
490 */
491 static class Index<K,V> {
492 final K key;
493 final Node<K,V> node;
494 final Index<K,V> down;
495 volatile Index<K,V> right;
496
497 /**
498 * Creates index node with unknown right pointer
499 */
500 Index(Node<K,V> node, Index<K,V> down) {
501 this.node = node;
502 this.key = node.key;
503 this.down = down;
504 }
505
506 /**
507 * Creates index node with known right pointer
508 */
509 Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) {
510 this.node = node;
511 this.key = node.key;
512 this.down = down;
513 this.right = right;
514 }
515
516 /** Updater for casRight */
517 static final AtomicReferenceFieldUpdater<Index, Index>
518 rightUpdater = AtomicReferenceFieldUpdater.newUpdater
519 (Index.class, Index.class, "right");
520
521 /**
522 * compareAndSet right field
523 */
524 final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
525 return rightUpdater.compareAndSet(this, cmp, val);
526 }
527
528 /**
529 * Returns true if the node this indexes has been deleted.
530 * @return true if indexed node is known to be deleted
531 */
532 final boolean indexesDeletedNode() {
533 return node.value == null;
534 }
535
536 /**
537 * Tries to CAS newSucc as successor. To minimize races with
538 * unlink that may lose this index node, if the node being
539 * indexed is known to be deleted, it doesn't try to link in.
540 * @param succ the expected current successor
541 * @param newSucc the new successor
542 * @return true if successful
543 */
544 final boolean link(Index<K,V> succ, Index<K,V> newSucc) {
545 Node<K,V> n = node;
546 newSucc.right = succ;
547 return n.value != null && casRight(succ, newSucc);
548 }
549
550 /**
551 * Tries to CAS right field to skip over apparent successor
552 * succ. Fails (forcing a retraversal by caller) if this node
553 * is known to be deleted.
554 * @param succ the expected current successor
555 * @return true if successful
556 */
557 final boolean unlink(Index<K,V> succ) {
558 return !indexesDeletedNode() && casRight(succ, succ.right);
559 }
560 }
561
562 /* ---------------- Head nodes -------------- */
563
564 /**
565 * Nodes heading each level keep track of their level.
566 */
567 static final class HeadIndex<K,V> extends Index<K,V> {
568 final int level;
569 HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right,
570 int level) {
571 super(node, down, right);
572 this.level = level;
573 }
574 }
575
576 /* ---------------- Map.Entry support -------------- */
577
578 /**
579 * An immutable representation of a key-value mapping as it
580 * existed at some point in time. This class does <em>not</em>
581 * support the <tt>Map.Entry.setValue</tt> method.
582 */
583 static class SnapshotEntry<K,V> implements Map.Entry<K,V> {
584 private final K key;
585 private final V value;
586
587 /**
588 * Creates a new entry representing the given key and value.
589 * @param key the key
590 * @param value the value
591 */
592 SnapshotEntry(K key, V value) {
593 this.key = key;
594 this.value = value;
595 }
596
597 /**
598 * Returns the key corresponding to this entry.
599 *
600 * @return the key corresponding to this entry.
601 */
602 public K getKey() {
603 return key;
604 }
605
606 /**
607 * Returns the value corresponding to this entry.
608 *
609 * @return the value corresponding to this entry.
610 */
611 public V getValue() {
612 return value;
613 }
614
615 /**
616 * Always fails, throwing <tt>UnsupportedOperationException</tt>.
617 * @throws UnsupportedOperationException always.
618 */
619 public V setValue(V value) {
620 throw new UnsupportedOperationException();
621 }
622
623 // inherit javadoc
624 public boolean equals(Object o) {
625 if (!(o instanceof Map.Entry))
626 return false;
627 Map.Entry e = (Map.Entry)o;
628 // As mandated by Map.Entry spec:
629 return ((key==null ?
630 e.getKey()==null : key.equals(e.getKey())) &&
631 (value==null ?
632 e.getValue()==null : value.equals(e.getValue())));
633 }
634
635
636 // inherit javadoc
637 public int hashCode() {
638 // As mandated by Map.Entry spec:
639 return ((key==null ? 0 : key.hashCode()) ^
640 (value==null ? 0 : value.hashCode()));
641 }
642
643 /**
644 * Returns a String consisting of the key followed by an
645 * equals sign (<tt>"="</tt>) followed by the associated
646 * value.
647 * @return a String representation of this entry.
648 */
649 public String toString() {
650 return getKey() + "=" + getValue();
651 }
652 }
653
654 /* ---------------- Comparison utilities -------------- */
655
656 /**
657 * Represents a key with a comparator as a Comparable.
658 *
659 * Because most sorted collections seem to use natural order on
660 * Comparables (Strings, Integers, etc), most internal methods are
661 * geared to use them. This is generally faster than checking
662 * per-comparison whether to use comparator or comparable because
663 * it doesn't require a (Comparable) cast for each comparison.
664 * (Optimizers can only sometimes remove such redundant checks
665 * themselves.) When Comparators are used,
666 * ComparableUsingComparators are created so that they act in the
667 * same way as natural orderings. This penalizes use of
668 * Comparators vs Comparables, which seems like the right
669 * tradeoff.
670 */
671 static final class ComparableUsingComparator<K> implements Comparable<K> {
672 final K actualKey;
673 final Comparator<? super K> cmp;
674 ComparableUsingComparator(K key, Comparator<? super K> cmp) {
675 this.actualKey = key;
676 this.cmp = cmp;
677 }
678 public int compareTo(K k2) {
679 return cmp.compare(actualKey, k2);
680 }
681 }
682
683 /**
684 * If using comparator, return a ComparableUsingComparator, else
685 * cast key as Comparator, which may cause ClassCastException,
686 * which is propagated back to caller.
687 */
688 private Comparable<K> comparable(Object key) throws ClassCastException {
689 if (key == null)
690 throw new NullPointerException();
691 return (comparator != null)
692 ? new ComparableUsingComparator(key, comparator)
693 : (Comparable<K>)key;
694 }
695
696 /**
697 * Compare using comparator or natural ordering. Used when the
698 * ComparableUsingComparator approach doesn't apply.
699 */
700 int compare(K k1, K k2) throws ClassCastException {
701 Comparator<? super K> cmp = comparator;
702 if (cmp != null)
703 return cmp.compare(k1, k2);
704 else
705 return ((Comparable<K>)k1).compareTo(k2);
706 }
707
708 /**
709 * Return true if given key greater than or equal to least and
710 * strictly less than fence. Needed mainly in submap operations.
711 */
712 boolean inHalfOpenRange(K key, K least, K fence) {
713 if (key == null)
714 throw new NullPointerException();
715 return ((least == null || compare(key, least) >= 0) &&
716 (fence == null || compare(key, fence) < 0));
717 }
718
719 /**
720 * Return true if given key greater than or equal to least and less
721 * or equal to fence. Needed mainly in submap operations.
722 */
723 boolean inOpenRange(K key, K least, K fence) {
724 if (key == null)
725 throw new NullPointerException();
726 return ((least == null || compare(key, least) >= 0) &&
727 (fence == null || compare(key, fence) <= 0));
728 }
729
730 /* ---------------- Traversal -------------- */
731
732 /**
733 * Return a base-level node with key strictly less than given key,
734 * or the base-level header if there is no such node. Also
735 * unlinks indexes to deleted nodes found along the way. Callers
736 * rely on this side-effect of clearing indices to deleted nodes.
737 * @param key the key
738 * @return a predecessor of key
739 */
740 private Node<K,V> findPredecessor(Comparable<K> key) {
741 for (;;) {
742 Index<K,V> q = head;
743 for (;;) {
744 Index<K,V> d, r;
745 if ((r = q.right) != null) {
746 if (r.indexesDeletedNode()) {
747 if (q.unlink(r))
748 continue; // reread r
749 else
750 break; // restart
751 }
752 if (key.compareTo(r.key) > 0) {
753 q = r;
754 continue;
755 }
756 }
757 if ((d = q.down) != null)
758 q = d;
759 else
760 return q.node;
761 }
762 }
763 }
764
765 /**
766 * Return node holding key or null if no such, clearing out any
767 * deleted nodes seen along the way. Repeatedly traverses at
768 * base-level looking for key starting at predecessor returned
769 * from findPredecessor, processing base-level deletions as
770 * encountered. Some callers rely on this side-effect of clearing
771 * deleted nodes.
772 *
773 * Restarts occur, at traversal step centered on node n, if:
774 *
775 * (1) After reading n's next field, n is no longer assumed
776 * predecessor b's current successor, which means that
777 * we don't have a consistent 3-node snapshot and so cannot
778 * unlink any subsequent deleted nodes encountered.
779 *
780 * (2) n's value field is null, indicating n is deleted, in
781 * which case we help out an ongoing structural deletion
782 * before retrying. Even though there are cases where such
783 * unlinking doesn't require restart, they aren't sorted out
784 * here because doing so would not usually outweigh cost of
785 * restarting.
786 *
787 * (3) n is a marker or n's predecessor's value field is null,
788 * indicating (among other possibilities) that
789 * findPredecessor returned a deleted node. We can't unlink
790 * the node because we don't know its predecessor, so rely
791 * on another call to findPredecessor to notice and return
792 * some earlier predecessor, which it will do. This check is
793 * only strictly needed at beginning of loop, (and the
794 * b.value check isn't strictly needed at all) but is done
795 * each iteration to help avoid contention with other
796 * threads by callers that will fail to be able to change
797 * links, and so will retry anyway.
798 *
799 * The traversal loops in doPut, doRemove, and findNear all
800 * include with the same three kinds of checks. And specialized
801 * versions appear in doRemoveFirstEntry, findFirst, and
802 * findLast. They can't easily share code because each uses the
803 * reads of fields held in locals occurring in the orders they
804 * were performed.
805 *
806 * @param key the key
807 * @return node holding key, or null if no such.
808 */
809 private Node<K,V> findNode(Comparable<K> key) {
810 for (;;) {
811 Node<K,V> b = findPredecessor(key);
812 Node<K,V> n = b.next;
813 for (;;) {
814 if (n == null)
815 return null;
816 Node<K,V> f = n.next;
817 if (n != b.next) // inconsistent read
818 break;
819 Object v = n.value;
820 if (v == null) { // n is deleted
821 n.helpDelete(b, f);
822 break;
823 }
824 if (v == n || b.value == null) // b is deleted
825 break;
826 int c = key.compareTo(n.key);
827 if (c < 0)
828 return null;
829 if (c == 0)
830 return n;
831 b = n;
832 n = f;
833 }
834 }
835 }
836
837 /**
838 * Specialized variant of findNode to perform map.get. Does a weak
839 * traversal, not bothering to fix any deleted index nodes,
840 * returning early if it happens to see key in index, and passing
841 * over any deleted base nodes, falling back to getUsingFindNode
842 * only if it would otherwise return value from an ongoing
843 * deletion. Also uses "bound" to eliminate need for some
844 * comparisons (see Pugh Cookbook). Also folds uses of null checks
845 * and node-skipping because markers have null keys.
846 * @param okey the key
847 * @return the value, or null if absent
848 */
849 private V doGet(Object okey) {
850 Comparable<K> key = comparable(okey);
851 K bound = null;
852 Index<K,V> q = head;
853 for (;;) {
854 K rk;
855 Index<K,V> d, r;
856 if ((r = q.right) != null &&
857 (rk = r.key) != null && rk != bound) {
858 int c = key.compareTo(rk);
859 if (c > 0) {
860 q = r;
861 continue;
862 }
863 if (c == 0) {
864 Object v = r.node.value;
865 return (v != null)? (V)v : getUsingFindNode(key);
866 }
867 bound = rk;
868 }
869 if ((d = q.down) != null)
870 q = d;
871 else {
872 for (Node<K,V> n = q.node.next; n != null; n = n.next) {
873 K nk = n.key;
874 if (nk != null) {
875 int c = key.compareTo(nk);
876 if (c == 0) {
877 Object v = n.value;
878 return (v != null)? (V)v : getUsingFindNode(key);
879 }
880 if (c < 0)
881 return null;
882 }
883 }
884 return null;
885 }
886 }
887 }
888
889 /**
890 * Perform map.get via findNode. Used as a backup if doGet
891 * encounters an in-progress deletion.
892 * @param key the key
893 * @return the value, or null if absent
894 */
895 private V getUsingFindNode(Comparable<K> key) {
896 // Loop needed here and elsewhere to protect against value
897 // field going null just as it is about to be returned.
898 for (;;) {
899 Node<K,V> n = findNode(key);
900 if (n == null)
901 return null;
902 Object v = n.value;
903 if (v != null)
904 return (V)v;
905 }
906 }
907
908 /* ---------------- Insertion -------------- */
909
910 /**
911 * Main insertion method. Adds element if not present, or
912 * replaces value if present and onlyIfAbsent is false.
913 * @param kkey the key
914 * @param value the value that must be associated with key
915 * @param onlyIfAbsent if should not insert if already present
916 * @return the old value, or null if newly inserted
917 */
918 private V doPut(K kkey, V value, boolean onlyIfAbsent) {
919 Comparable<K> key = comparable(kkey);
920 for (;;) {
921 Node<K,V> b = findPredecessor(key);
922 Node<K,V> n = b.next;
923 for (;;) {
924 if (n != null) {
925 Node<K,V> f = n.next;
926 if (n != b.next) // inconsistent read
927 break;;
928 Object v = n.value;
929 if (v == null) { // n is deleted
930 n.helpDelete(b, f);
931 break;
932 }
933 if (v == n || b.value == null) // b is deleted
934 break;
935 int c = key.compareTo(n.key);
936 if (c > 0) {
937 b = n;
938 n = f;
939 continue;
940 }
941 if (c == 0) {
942 if (onlyIfAbsent || n.casValue(v, value))
943 return (V)v;
944 else
945 break; // restart if lost race to replace value
946 }
947 // else c < 0; fall through
948 }
949
950 Node<K,V> z = new Node<K,V>(kkey, value, n);
951 if (!b.casNext(n, z))
952 break; // restart if lost race to append to b
953 int level = randomLevel();
954 if (level > 0)
955 insertIndex(z, level);
956 return null;
957 }
958 }
959 }
960
961 /**
962 * Return a random level for inserting a new node.
963 * Hardwired to k=1, p=0.5, max 31.
964 *
965 * This uses a cheap pseudo-random function that according to
966 * http://home1.gte.net/deleyd/random/random4.html was used in
967 * Turbo Pascal. It seems the fastest usable one here. The low
968 * bits are apparently not very random (the original used only
969 * upper 16 bits) so we traverse from highest bit down (i.e., test
970 * sign), thus hardly ever use lower bits.
971 */
972 private int randomLevel() {
973 int level = 0;
974 int r = randomSeed;
975 randomSeed = r * 134775813 + 1;
976 if (r < 0) {
977 while ((r <<= 1) > 0)
978 ++level;
979 }
980 return level;
981 }
982
983 /**
984 * Create and add index nodes for given node.
985 * @param z the node
986 * @param level the level of the index
987 */
988 private void insertIndex(Node<K,V> z, int level) {
989 HeadIndex<K,V> h = head;
990 int max = h.level;
991
992 if (level <= max) {
993 Index<K,V> idx = null;
994 for (int i = 1; i <= level; ++i)
995 idx = new Index<K,V>(z, idx);
996 addIndex(idx, h, level);
997
998 } else { // Add a new level
999 /*
1000 * To reduce interference by other threads checking for
1001 * empty levels in tryReduceLevel, new levels are added
1002 * with initialized right pointers. Which in turn requires
1003 * keeping levels in an array to access them while
1004 * creating new head index nodes from the opposite
1005 * direction.
1006 */
1007 level = max + 1;
1008 Index<K,V>[] idxs = (Index<K,V>[])new Index[level+1];
1009 Index<K,V> idx = null;
1010 for (int i = 1; i <= level; ++i)
1011 idxs[i] = idx = new Index<K,V>(z, idx);
1012
1013 HeadIndex<K,V> oldh;
1014 int k;
1015 for (;;) {
1016 oldh = head;
1017 int oldLevel = oldh.level;
1018 if (level <= oldLevel) { // lost race to add level
1019 k = level;
1020 break;
1021 }
1022 HeadIndex<K,V> newh = oldh;
1023 Node<K,V> oldbase = oldh.node;
1024 for (int j = oldLevel+1; j <= level; ++j)
1025 newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
1026 if (casHead(oldh, newh)) {
1027 k = oldLevel;
1028 break;
1029 }
1030 }
1031 addIndex(idxs[k], oldh, k);
1032 }
1033 }
1034
1035 /**
1036 * Add given index nodes from given level down to 1.
1037 * @param idx the topmost index node being inserted
1038 * @param h the value of head to use to insert. This must be
1039 * snapshotted by callers to provide correct insertion level
1040 * @param indexLevel the level of the index
1041 */
1042 private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
1043 // Track next level to insert in case of retries
1044 int insertionLevel = indexLevel;
1045 Comparable<K> key = comparable(idx.key);
1046
1047 // Similar to findPredecessor, but adding index nodes along
1048 // path to key.
1049 for (;;) {
1050 Index<K,V> q = h;
1051 Index<K,V> t = idx;
1052 int j = h.level;
1053 for (;;) {
1054 Index<K,V> r = q.right;
1055 if (r != null) {
1056 // compare before deletion check avoids needing recheck
1057 int c = key.compareTo(r.key);
1058 if (r.indexesDeletedNode()) {
1059 if (q.unlink(r))
1060 continue;
1061 else
1062 break;
1063 }
1064 if (c > 0) {
1065 q = r;
1066 continue;
1067 }
1068 }
1069
1070 if (j == insertionLevel) {
1071 // Don't insert index if node already deleted
1072 if (t.indexesDeletedNode()) {
1073 findNode(key); // cleans up
1074 return;
1075 }
1076 if (!q.link(r, t))
1077 break; // restart
1078 if (--insertionLevel == 0) {
1079 // need final deletion check before return
1080 if (t.indexesDeletedNode())
1081 findNode(key);
1082 return;
1083 }
1084 }
1085
1086 if (j > insertionLevel && j <= indexLevel)
1087 t = t.down;
1088 q = q.down;
1089 --j;
1090 }
1091 }
1092 }
1093
1094 /* ---------------- Deletion -------------- */
1095
1096 /**
1097 * Main deletion method. Locates node, nulls value, appends a
1098 * deletion marker, unlinks predecessor, removes associated index
1099 * nodes, and possibly reduces head index level.
1100 *
1101 * Index node are cleared out simply by calling findPredecessor.
1102 * which unlinks indexes to deleted nodes found along path to key,
1103 * which will include the indexes to this node. This is done
1104 * unconditionally. We can't check beforehand whether there are
1105 * index nodes because it might be the case that some or all
1106 * indexes hadn't been inserted yet for this node during initial
1107 * search for it, and we'd like to ensure lack of garbage
1108 * retention, so must call to be sure.
1109 *
1110 * @param okey the key
1111 * @param value if non-null, the value that must be
1112 * associated with key
1113 * @return the node, or null if not found
1114 */
1115 private V doRemove(Object okey, Object value) {
1116 Comparable<K> key = comparable(okey);
1117 for (;;) {
1118 Node<K,V> b = findPredecessor(key);
1119 Node<K,V> n = b.next;
1120 for (;;) {
1121 if (n == null)
1122 return null;
1123 Node<K,V> f = n.next;
1124 if (n != b.next) // inconsistent read
1125 break;
1126 Object v = n.value;
1127 if (v == null) { // n is deleted
1128 n.helpDelete(b, f);
1129 break;
1130 }
1131 if (v == n || b.value == null) // b is deleted
1132 break;
1133 int c = key.compareTo(n.key);
1134 if (c < 0)
1135 return null;
1136 if (c > 0) {
1137 b = n;
1138 n = f;
1139 continue;
1140 }
1141 if (value != null && !value.equals(v))
1142 return null;
1143 if (!n.casValue(v, null))
1144 break;
1145 if (!n.appendMarker(f) || !b.casNext(n, f))
1146 findNode(key); // Retry via findNode
1147 else {
1148 findPredecessor(key); // Clean index
1149 if (head.right == null)
1150 tryReduceLevel();
1151 }
1152 return (V)v;
1153 }
1154 }
1155 }
1156
1157 /**
1158 * Possibly reduce head level if it has no nodes. This method can
1159 * (rarely) make mistakes, in which case levels can disappear even
1160 * though they are about to contain index nodes. This impacts
1161 * performance, not correctness. To minimize mistakes and also to
1162 * reduce hysteresis, the level is reduced by one only if the
1163 * topmost three levels look empty. Also, if the removed level
1164 * looks non-empty after CAS, we try to change it back quick
1165 * before anyone notices our mistake! (This trick works pretty
1166 * well because this method will practically never make mistakes
1167 * unless current thread stalls immediately before first CAS, in
1168 * which case it is very unlikely to stall again immediately
1169 * afterwards, so will recover.)
1170 *
1171 * We put up with all this rather than just let levels grow
1172 * because otherwise, even a small map that has undergone a large
1173 * number of insertions and removals will have a lot of levels,
1174 * slowing down access more than would an occasional unwanted
1175 * reduction.
1176 */
1177 private void tryReduceLevel() {
1178 HeadIndex<K,V> h = head;
1179 HeadIndex<K,V> d;
1180 HeadIndex<K,V> e;
1181 if (h.level > 3 &&
1182 (d = (HeadIndex<K,V>)h.down) != null &&
1183 (e = (HeadIndex<K,V>)d.down) != null &&
1184 e.right == null &&
1185 d.right == null &&
1186 h.right == null &&
1187 casHead(h, d) && // try to set
1188 h.right != null) // recheck
1189 casHead(d, h); // try to backout
1190 }
1191
1192
1193 /* ---------------- Positional operations -------------- */
1194
1195 /**
1196 * Specialized version of find to get first valid node
1197 * @return first node or null if empty
1198 */
1199 Node<K,V> findFirst() {
1200 for (;;) {
1201 // cheaper checks because we know head is never deleted
1202 Node<K,V> b = head.node;
1203 Node<K,V> n = b.next;
1204 if (n == null)
1205 return null;
1206 if (n.value != null)
1207 return n;
1208 n.helpDelete(b, n.next);
1209 }
1210 }
1211
1212 /**
1213 * Remove first entry; return its key or null if empty.
1214 * Used by ConcurrentSkipListSet
1215 */
1216 K removeFirstKey() {
1217 for (;;) {
1218 Node<K,V> b = head.node;
1219 Node<K,V> n = b.next;
1220 if (n == null)
1221 return null;
1222 Node<K,V> f = n.next;
1223 if (n != b.next)
1224 continue;
1225 Object v = n.value;
1226 if (v == null) {
1227 n.helpDelete(b, f);
1228 continue;
1229 }
1230 if (!n.casValue(v, null))
1231 continue;
1232 if (!n.appendMarker(f) || !b.casNext(n, f))
1233 findFirst(); // retry
1234 clearIndexToFirst();
1235 return n.key;
1236 }
1237 }
1238
1239 /**
1240 * Remove first entry; return SnapshotEntry or null if empty.
1241 */
1242 private SnapshotEntry<K,V> doRemoveFirstEntry() {
1243 /*
1244 * This must be mostly duplicated from removeFirstKey because we
1245 * need to save the last value read before it is nulled out
1246 */
1247 for (;;) {
1248 Node<K,V> b = head.node;
1249 Node<K,V> n = b.next;
1250 if (n == null)
1251 return null;
1252 Node<K,V> f = n.next;
1253 if (n != b.next)
1254 continue;
1255 Object v = n.value;
1256 if (v == null) {
1257 n.helpDelete(b, f);
1258 continue;
1259 }
1260 if (!n.casValue(v, null))
1261 continue;
1262 if (!n.appendMarker(f) || !b.casNext(n, f))
1263 findFirst(); // retry
1264 clearIndexToFirst();
1265 return new SnapshotEntry<K,V>(n.key, (V)v);
1266 }
1267 }
1268
1269 /**
1270 * Clear out index nodes associated with deleted first entry.
1271 * Needed by removeFirstKey and removeFirstEntry
1272 */
1273 private void clearIndexToFirst() {
1274 for (;;) {
1275 Index<K,V> q = head;
1276 for (;;) {
1277 Index<K,V> r = q.right;
1278 if (r != null && r.indexesDeletedNode() && !q.unlink(r))
1279 break;
1280 if ((q = q.down) == null) {
1281 if (head.right == null)
1282 tryReduceLevel();
1283 return;
1284 }
1285 }
1286 }
1287 }
1288
1289 /**
1290 * Specialized version of find to get last valid node
1291 * @return last node or null if empty
1292 */
1293 Node<K,V> findLast() {
1294 /*
1295 * findPredecessor can't be used to traverse index level
1296 * because this doesn't use comparisons. So traversals of
1297 * both levels are folded together.
1298 */
1299 Index<K,V> q = head;
1300 for (;;) {
1301 Index<K,V> d, r;
1302 if ((r = q.right) != null) {
1303 if (r.indexesDeletedNode()) {
1304 q.unlink(r);
1305 q = head; // restart
1306 }
1307 else
1308 q = r;
1309 } else if ((d = q.down) != null) {
1310 q = d;
1311 } else {
1312 Node<K,V> b = q.node;
1313 Node<K,V> n = b.next;
1314 for (;;) {
1315 if (n == null)
1316 return (b.isBaseHeader())? null : b;
1317 Node<K,V> f = n.next; // inconsistent read
1318 if (n != b.next)
1319 break;
1320 Object v = n.value;
1321 if (v == null) { // n is deleted
1322 n.helpDelete(b, f);
1323 break;
1324 }
1325 if (v == n || b.value == null) // b is deleted
1326 break;
1327 b = n;
1328 n = f;
1329 }
1330 q = head; // restart
1331 }
1332 }
1333 }
1334
1335 /**
1336 * Temporary helper method for two-pass implementation of
1337 * removeLastEntry, mostly pasted from doRemove.
1338 * TODO: replace with one-pass implementation
1339 */
1340 private Object removeIfLast(K kkey) {
1341 Comparable<K> key = comparable(kkey);
1342 for (;;) {
1343 Node<K,V> b = findPredecessor(key);
1344 Node<K,V> n = b.next;
1345 for (;;) {
1346 if (n == null)
1347 return null;
1348 Node<K,V> f = n.next;
1349 if (n != b.next) // inconsistent read
1350 break;
1351 Object v = n.value;
1352 if (v == null) { // n is deleted
1353 n.helpDelete(b, f);
1354 break;
1355 }
1356 if (v == n || b.value == null) // b is deleted
1357 break;
1358 int c = key.compareTo(n.key);
1359 if (c < 0)
1360 return null;
1361 if (c > 0) {
1362 b = n;
1363 n = f;
1364 continue;
1365 }
1366 if (f != null) // fail if n not last
1367 return null;
1368 if (!n.casValue(v, null))
1369 return null;
1370 if (!n.appendMarker(f) || !b.casNext(n, f))
1371 findNode(key); // Retry via findNode
1372 else {
1373 findPredecessor(key); // Clean index
1374 if (head.right == null)
1375 tryReduceLevel();
1376 }
1377 return v;
1378 }
1379 }
1380 }
1381
1382 /**
1383 * Remove last entry; return SnapshotEntry or null if empty.
1384 */
1385 private SnapshotEntry<K,V> doRemoveLastEntry() {
1386 for (;;) {
1387 Node<K,V> l = findLast();
1388 if (l == null)
1389 return null;
1390 K k = l.key;
1391 Object v = removeIfLast(k);
1392 if (v != null)
1393 return new SnapshotEntry<K, V>(k, (V)v);
1394 }
1395 }
1396
1397 /**
1398 * Remove last entry; return key or null if empty.
1399 */
1400 K removeLastKey() {
1401 for (;;) {
1402 Node<K,V> l = findLast();
1403 if (l == null)
1404 return null;
1405 K k = l.key;
1406 if (removeIfLast(k) != null)
1407 return k;
1408 }
1409 }
1410
1411 /* ---------------- Relational operations -------------- */
1412
1413 // Control values OR'ed as arguments to findNear
1414
1415 private static final int EQ = 1;
1416 private static final int LT = 2;
1417 private static final int GT = 0;
1418
1419 /**
1420 * Utility for ceiling, floor, lower, higher methods.
1421 * @param kkey the key
1422 * @param rel the relation -- OR'ed combination of EQ, LT, GT
1423 * @return nearest node fitting relation, or null if no such
1424 */
1425 Node<K,V> findNear(K kkey, int rel) {
1426 Comparable<K> key = comparable(kkey);
1427 for (;;) {
1428 Node<K,V> b = findPredecessor(key);
1429 Node<K,V> n = b.next;
1430 for (;;) {
1431 if (n == null)
1432 return ((rel & LT) == 0 || b.isBaseHeader())? null : b;
1433 Node<K,V> f = n.next;
1434 if (n != b.next) // inconsistent read
1435 break;
1436 Object v = n.value;
1437 if (v == null) { // n is deleted
1438 n.helpDelete(b, f);
1439 break;
1440 }
1441 if (v == n || b.value == null) // b is deleted
1442 break;
1443 int c = key.compareTo(n.key);
1444 if ((c == 0 && (rel & EQ) != 0) ||
1445 (c < 0 && (rel & LT) == 0))
1446 return n;
1447 if ( c <= 0 && (rel & LT) != 0)
1448 return (b.isBaseHeader())? null : b;
1449 b = n;
1450 n = f;
1451 }
1452 }
1453 }
1454
1455 /**
1456 * Return SnapshotEntry for results of findNear.
1457 * @param kkey the key
1458 * @param rel the relation -- OR'ed combination of EQ, LT, GT
1459 * @return Entry fitting relation, or null if no such
1460 */
1461 SnapshotEntry<K,V> getNear(K kkey, int rel) {
1462 for (;;) {
1463 Node<K,V> n = findNear(kkey, rel);
1464 if (n == null)
1465 return null;
1466 SnapshotEntry<K,V> e = n.createSnapshot();
1467 if (e != null)
1468 return e;
1469 }
1470 }
1471
1472 /* ---------------- Constructors -------------- */
1473
1474 /**
1475 * Constructs a new empty map, sorted according to the keys' natural
1476 * order.
1477 */
1478 public ConcurrentSkipListMap() {
1479 this.comparator = null;
1480 initialize();
1481 }
1482
1483 /**
1484 * Constructs a new empty map, sorted according to the given comparator.
1485 *
1486 * @param c the comparator that will be used to sort this map. A
1487 * <tt>null</tt> value indicates that the keys' <i>natural
1488 * ordering</i> should be used.
1489 */
1490 public ConcurrentSkipListMap(Comparator<? super K> c) {
1491 this.comparator = c;
1492 initialize();
1493 }
1494
1495 /**
1496 * Constructs a new map containing the same mappings as the given map,
1497 * sorted according to the keys' <i>natural order</i>.
1498 *
1499 * @param m the map whose mappings are to be placed in this map.
1500 * @throws ClassCastException if the keys in m are not Comparable, or
1501 * are not mutually comparable.
1502 * @throws NullPointerException if the specified map is <tt>null</tt>.
1503 */
1504 public ConcurrentSkipListMap(Map<? extends K, ? extends V> m) {
1505 this.comparator = null;
1506 initialize();
1507 putAll(m);
1508 }
1509
1510 /**
1511 * Constructs a new map containing the same mappings as the given
1512 * <tt>SortedMap</tt>, sorted according to the same ordering.
1513 * @param m the sorted map whose mappings are to be placed in this map,
1514 * and whose comparator is to be used to sort this map.
1515 * @throws NullPointerException if the specified sorted map is <tt>null</tt>.
1516 */
1517 public ConcurrentSkipListMap(SortedMap<K, ? extends V> m) {
1518 this.comparator = m.comparator();
1519 initialize();
1520 buildFromSorted(m);
1521 }
1522
1523 /**
1524 * Returns a shallow copy of this <tt>Map</tt> instance. (The keys and
1525 * values themselves are not cloned.)
1526 *
1527 * @return a shallow copy of this Map.
1528 */
1529 public Object clone() {
1530 ConcurrentSkipListMap<K,V> clone = null;
1531 try {
1532 clone = (ConcurrentSkipListMap<K,V>) super.clone();
1533 } catch (CloneNotSupportedException e) {
1534 throw new InternalError();
1535 }
1536
1537 clone.initialize();
1538 clone.buildFromSorted(this);
1539 return clone;
1540 }
1541
1542 /**
1543 * Streamlined bulk insertion to initialize from elements of
1544 * given sorted map. Call only from constructor or clone
1545 * method.
1546 */
1547 private void buildFromSorted(SortedMap<K, ? extends V> map) {
1548 if (map == null)
1549 throw new NullPointerException();
1550
1551 HeadIndex<K,V> h = head;
1552 Node<K,V> basepred = h.node;
1553
1554 // Track the current rightmost node at each level. Uses an
1555 // ArrayList to avoid committing to initial or maximum level.
1556 ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
1557
1558 // initialize
1559 for (int i = 0; i <= h.level; ++i)
1560 preds.add(null);
1561 Index<K,V> q = h;
1562 for (int i = h.level; i > 0; --i) {
1563 preds.set(i, q);
1564 q = q.down;
1565 }
1566
1567 Iterator<? extends Map.Entry<? extends K, ? extends V>> it =
1568 map.entrySet().iterator();
1569 while (it.hasNext()) {
1570 Map.Entry<? extends K, ? extends V> e = it.next();
1571 int j = randomLevel();
1572 if (j > h.level) j = h.level + 1;
1573 K k = e.getKey();
1574 V v = e.getValue();
1575 if (k == null || v == null)
1576 throw new NullPointerException();
1577 Node<K,V> z = new Node<K,V>(k, v, null);
1578 basepred.next = z;
1579 basepred = z;
1580 if (j > 0) {
1581 Index<K,V> idx = null;
1582 for (int i = 1; i <= j; ++i) {
1583 idx = new Index<K,V>(z, idx);
1584 if (i > h.level)
1585 h = new HeadIndex<K,V>(h.node, h, idx, i);
1586
1587 if (i < preds.size()) {
1588 preds.get(i).right = idx;
1589 preds.set(i, idx);
1590 } else
1591 preds.add(idx);
1592 }
1593 }
1594 }
1595 head = h;
1596 }
1597
1598 /* ---------------- Serialization -------------- */
1599
1600 /**
1601 * Save the state of the <tt>Map</tt> instance to a stream.
1602 *
1603 * @serialData The key (Object) and value (Object) for each
1604 * key-value mapping represented by the Map, followed by
1605 * <tt>null</tt>. The key-value mappings are emitted in key-order
1606 * (as determined by the Comparator, or by the keys' natural
1607 * ordering if no Comparator).
1608 */
1609 private void writeObject(java.io.ObjectOutputStream s)
1610 throws java.io.IOException {
1611 // Write out the Comparator and any hidden stuff
1612 s.defaultWriteObject();
1613
1614 // Write out keys and values (alternating)
1615 for (Node<K,V> n = findFirst(); n != null; n = n.next) {
1616 V v = n.getValidValue();
1617 if (v != null) {
1618 s.writeObject(n.key);
1619 s.writeObject(v);
1620 }
1621 }
1622 s.writeObject(null);
1623 }
1624
1625 /**
1626 * Reconstitute the <tt>Map</tt> instance from a stream.
1627 */
1628 private void readObject(final java.io.ObjectInputStream s)
1629 throws java.io.IOException, ClassNotFoundException {
1630 // Read in the Comparator and any hidden stuff
1631 s.defaultReadObject();
1632 // Reset transients
1633 initialize();
1634
1635 /*
1636 * This is basically identical to buildFromSorted, but is
1637 * distinct because readObject calls can't be nicely adapted
1638 * as the kind of iterator needed by buildFromSorted. (They
1639 * can be, but doing so requires type cheats and/or creation
1640 * of adaptor classes.) It is simpler to just adapt the code.
1641 */
1642
1643 HeadIndex<K,V> h = head;
1644 Node<K,V> basepred = h.node;
1645 ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
1646 for (int i = 0; i <= h.level; ++i)
1647 preds.add(null);
1648 Index<K,V> q = h;
1649 for (int i = h.level; i > 0; --i) {
1650 preds.set(i, q);
1651 q = q.down;
1652 }
1653
1654 for (;;) {
1655 Object k = s.readObject();
1656 if (k == null)
1657 break;
1658 Object v = s.readObject();
1659 if (v == null)
1660 throw new NullPointerException();
1661 K key = (K) k;
1662 V val = (V) v;
1663 int j = randomLevel();
1664 if (j > h.level) j = h.level + 1;
1665 Node<K,V> z = new Node<K,V>(key, val, null);
1666 basepred.next = z;
1667 basepred = z;
1668 if (j > 0) {
1669 Index<K,V> idx = null;
1670 for (int i = 1; i <= j; ++i) {
1671 idx = new Index<K,V>(z, idx);
1672 if (i > h.level)
1673 h = new HeadIndex<K,V>(h.node, h, idx, i);
1674
1675 if (i < preds.size()) {
1676 preds.get(i).right = idx;
1677 preds.set(i, idx);
1678 } else
1679 preds.add(idx);
1680 }
1681 }
1682 }
1683 head = h;
1684 }
1685
1686 /* ------ Map API methods ------ */
1687
1688 /**
1689 * Returns <tt>true</tt> if this map contains a mapping for the specified
1690 * key.
1691 * @param key key whose presence in this map is to be tested.
1692 * @return <tt>true</tt> if this map contains a mapping for the
1693 * specified key.
1694 * @throws ClassCastException if the key cannot be compared with the keys
1695 * currently in the map.
1696 * @throws NullPointerException if the key is <tt>null</tt>.
1697 */
1698 public boolean containsKey(Object key) {
1699 return doGet(key) != null;
1700 }
1701
1702 /**
1703 * Returns the value to which this map maps the specified key. Returns
1704 * <tt>null</tt> if the map contains no mapping for this key.
1705 *
1706 * @param key key whose associated value is to be returned.
1707 * @return the value to which this map maps the specified key, or
1708 * <tt>null</tt> if the map contains no mapping for the key.
1709 * @throws ClassCastException if the key cannot be compared with the keys
1710 * currently in the map.
1711 * @throws NullPointerException if the key is <tt>null</tt>.
1712 */
1713 public V get(Object key) {
1714 return doGet(key);
1715 }
1716
1717 /**
1718 * Associates the specified value with the specified key in this map.
1719 * If the map previously contained a mapping for this key, the old
1720 * value is replaced.
1721 *
1722 * @param key key with which the specified value is to be associated.
1723 * @param value value to be associated with the specified key.
1724 *
1725 * @return previous value associated with specified key, or <tt>null</tt>
1726 * if there was no mapping for key.
1727 * @throws ClassCastException if the key cannot be compared with the keys
1728 * currently in the map.
1729 * @throws NullPointerException if the key or value are <tt>null</tt>.
1730 */
1731 public V put(K key, V value) {
1732 if (value == null)
1733 throw new NullPointerException();
1734 return doPut(key, value, false);
1735 }
1736
1737 /**
1738 * Removes the mapping for this key from this Map if present.
1739 *
1740 * @param key key for which mapping should be removed
1741 * @return previous value associated with specified key, or <tt>null</tt>
1742 * if there was no mapping for key.
1743 *
1744 * @throws ClassCastException if the key cannot be compared with the keys
1745 * currently in the map.
1746 * @throws NullPointerException if the key is <tt>null</tt>.
1747 */
1748 public V remove(Object key) {
1749 return doRemove(key, null);
1750 }
1751
1752 /**
1753 * Returns <tt>true</tt> if this map maps one or more keys to the
1754 * specified value. This operation requires time linear in the
1755 * Map size.
1756 *
1757 * @param value value whose presence in this Map is to be tested.
1758 * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
1759 * <tt>false</tt> otherwise.
1760 * @throws NullPointerException if the value is <tt>null</tt>.
1761 */
1762 public boolean containsValue(Object value) {
1763 if (value == null)
1764 throw new NullPointerException();
1765 for (Node<K,V> n = findFirst(); n != null; n = n.next) {
1766 V v = n.getValidValue();
1767 if (v != null && value.equals(v))
1768 return true;
1769 }
1770 return false;
1771 }
1772
1773 /**
1774 * Returns the number of elements in this map. If this map
1775 * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
1776 * returns <tt>Integer.MAX_VALUE</tt>.
1777 *
1778 * <p>Beware that, unlike in most collections, this method is
1779 * <em>NOT</em> a constant-time operation. Because of the
1780 * asynchronous nature of these maps, determining the current
1781 * number of elements requires traversing them all to count them.
1782 * Additionally, it is possible for the size to change during
1783 * execution of this method, in which case the returned result
1784 * will be inaccurate. Thus, this method is typically not very
1785 * useful in concurrent applications.
1786 *
1787 * @return the number of elements in this map.
1788 */
1789 public int size() {
1790 long count = 0;
1791 for (Node<K,V> n = findFirst(); n != null; n = n.next) {
1792 if (n.getValidValue() != null)
1793 ++count;
1794 }
1795 return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count;
1796 }
1797
1798 /**
1799 * Returns <tt>true</tt> if this map contains no key-value mappings.
1800 * @return <tt>true</tt> if this map contains no key-value mappings.
1801 */
1802 public boolean isEmpty() {
1803 return findFirst() == null;
1804 }
1805
1806 /**
1807 * Removes all mappings from this map.
1808 */
1809 public void clear() {
1810 initialize();
1811 }
1812
1813 /**
1814 * Returns a set view of the keys contained in this map. The set is
1815 * backed by the map, so changes to the map are reflected in the set, and
1816 * vice-versa. The set supports element removal, which removes the
1817 * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
1818 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
1819 * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
1820 * <tt>addAll</tt> operations.
1821 * The view's <tt>iterator</tt> is a "weakly consistent" iterator that
1822 * will never throw {@link java.util.ConcurrentModificationException},
1823 * and guarantees to traverse elements as they existed upon
1824 * construction of the iterator, and may (but is not guaranteed to)
1825 * reflect any modifications subsequent to construction.
1826 *
1827 * @return a set view of the keys contained in this map.
1828 */
1829 public Set<K> keySet() {
1830 /*
1831 * Note: Lazy intialization works here and for other views
1832 * because view classes are stateless/immutable so it doesn't
1833 * matter wrt correctness if more than one is created (which
1834 * will only rarely happen). Even so, the following idiom
1835 * conservatively ensures that the method returns the one it
1836 * created if it does so, not one created by another racing
1837 * thread.
1838 */
1839 KeySet ks = keySet;
1840 return (ks != null) ? ks : (keySet = new KeySet());
1841 }
1842
1843 /**
1844 * Returns a collection view of the values contained in this map.
1845 * The collection is backed by the map, so changes to the map are
1846 * reflected in the collection, and vice-versa. The collection
1847 * supports element removal, which removes the corresponding
1848 * mapping from this map, via the <tt>Iterator.remove</tt>,
1849 * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1850 * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
1851 * support the <tt>add</tt> or <tt>addAll</tt> operations. The
1852 * view's <tt>iterator</tt> is a "weakly consistent" iterator that
1853 * will never throw {@link
1854 * java.util.ConcurrentModificationException}, and guarantees to
1855 * traverse elements as they existed upon construction of the
1856 * iterator, and may (but is not guaranteed to) reflect any
1857 * modifications subsequent to construction.
1858 *
1859 * @return a collection view of the values contained in this map.
1860 */
1861 public Collection<V> values() {
1862 Values vs = values;
1863 return (vs != null) ? vs : (values = new Values());
1864 }
1865
1866 /**
1867 * Returns a collection view of the mappings contained in this
1868 * map. Each element in the returned collection is a
1869 * <tt>Map.Entry</tt>. The collection is backed by the map, so
1870 * changes to the map are reflected in the collection, and
1871 * vice-versa. The collection supports element removal, which
1872 * removes the corresponding mapping from the map, via the
1873 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
1874 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
1875 * operations. It does not support the <tt>add</tt> or
1876 * <tt>addAll</tt> operations. The view's <tt>iterator</tt> is a
1877 * "weakly consistent" iterator that will never throw {@link
1878 * java.util.ConcurrentModificationException}, and guarantees to
1879 * traverse elements as they existed upon construction of the
1880 * iterator, and may (but is not guaranteed to) reflect any
1881 * modifications subsequent to construction. The
1882 * <tt>Map.Entry</tt> elements returned by
1883 * <tt>iterator.next()</tt> do <em>not</em> support the
1884 * <tt>setValue</tt> operation.
1885 *
1886 * @return a collection view of the mappings contained in this map.
1887 */
1888 public Set<Map.Entry<K,V>> entrySet() {
1889 EntrySet es = entrySet;
1890 return (es != null) ? es : (entrySet = new EntrySet());
1891 }
1892
1893 /* ------ ConcurrentMap API methods ------ */
1894
1895 /**
1896 * If the specified key is not already associated
1897 * with a value, associate it with the given value.
1898 * This is equivalent to
1899 * <pre>
1900 * if (!map.containsKey(key))
1901 * return map.put(key, value);
1902 * else
1903 * return map.get(key);
1904 * </pre>
1905 * Except that the action is performed atomically.
1906 * @param key key with which the specified value is to be associated.
1907 * @param value value to be associated with the specified key.
1908 * @return previous value associated with specified key, or <tt>null</tt>
1909 * if there was no mapping for key.
1910 *
1911 * @throws ClassCastException if the key cannot be compared with the keys
1912 * currently in the map.
1913 * @throws NullPointerException if the key or value are <tt>null</tt>.
1914 */
1915 public V putIfAbsent(K key, V value) {
1916 if (value == null)
1917 throw new NullPointerException();
1918 return doPut(key, value, true);
1919 }
1920
1921 /**
1922 * Remove entry for key only if currently mapped to given value.
1923 * Acts as
1924 * <pre>
1925 * if ((map.containsKey(key) && map.get(key).equals(value)) {
1926 * map.remove(key);
1927 * return true;
1928 * } else return false;
1929 * </pre>
1930 * except that the action is performed atomically.
1931 * @param key key with which the specified value is associated.
1932 * @param value value associated with the specified key.
1933 * @return true if the value was removed, false otherwise
1934 * @throws ClassCastException if the key cannot be compared with the keys
1935 * currently in the map.
1936 * @throws NullPointerException if the key or value are <tt>null</tt>.
1937 */
1938 public boolean remove(Object key, Object value) {
1939 if (value == null)
1940 throw new NullPointerException();
1941 return doRemove(key, value) != null;
1942 }
1943
1944 /**
1945 * Replace entry for key only if currently mapped to given value.
1946 * Acts as
1947 * <pre>
1948 * if ((map.containsKey(key) && map.get(key).equals(oldValue)) {
1949 * map.put(key, newValue);
1950 * return true;
1951 * } else return false;
1952 * </pre>
1953 * except that the action is performed atomically.
1954 * @param key key with which the specified value is associated.
1955 * @param oldValue value expected to be associated with the specified key.
1956 * @param newValue value to be associated with the specified key.
1957 * @return true if the value was replaced
1958 * @throws ClassCastException if the key cannot be compared with the keys
1959 * currently in the map.
1960 * @throws NullPointerException if key, oldValue or newValue are
1961 * <tt>null</tt>.
1962 */
1963 public boolean replace(K key, V oldValue, V newValue) {
1964 if (oldValue == null || newValue == null)
1965 throw new NullPointerException();
1966 Comparable<K> k = comparable(key);
1967 for (;;) {
1968 Node<K,V> n = findNode(k);
1969 if (n == null)
1970 return false;
1971 Object v = n.value;
1972 if (v != null) {
1973 if (!oldValue.equals(v))
1974 return false;
1975 if (n.casValue(v, newValue))
1976 return true;
1977 }
1978 }
1979 }
1980
1981 /**
1982 * Replace entry for key only if currently mapped to some value.
1983 * Acts as
1984 * <pre>
1985 * if ((map.containsKey(key)) {
1986 * return map.put(key, value);
1987 * } else return null;
1988 * </pre>
1989 * except that the action is performed atomically.
1990 * @param key key with which the specified value is associated.
1991 * @param value value to be associated with the specified key.
1992 * @return previous value associated with specified key, or <tt>null</tt>
1993 * if there was no mapping for key.
1994 * @throws ClassCastException if the key cannot be compared with the keys
1995 * currently in the map.
1996 * @throws NullPointerException if the key or value are <tt>null</tt>.
1997 */
1998 public V replace(K key, V value) {
1999 if (value == null)
2000 throw new NullPointerException();
2001 Comparable<K> k = comparable(key);
2002 for (;;) {
2003 Node<K,V> n = findNode(k);
2004 if (n == null)
2005 return null;
2006 Object v = n.value;
2007 if (v != null && n.casValue(v, value))
2008 return (V)v;
2009 }
2010 }
2011
2012 /* ------ SortedMap API methods ------ */
2013
2014 /**
2015 * Returns the comparator used to order this map, or <tt>null</tt>
2016 * if this map uses its keys' natural order.
2017 *
2018 * @return the comparator associated with this map, or
2019 * <tt>null</tt> if it uses its keys' natural sort method.
2020 */
2021 public Comparator<? super K> comparator() {
2022 return comparator;
2023 }
2024
2025 /**
2026 * Returns the first (lowest) key currently in this map.
2027 *
2028 * @return the first (lowest) key currently in this map.
2029 * @throws NoSuchElementException Map is empty.
2030 */
2031 public K firstKey() {
2032 Node<K,V> n = findFirst();
2033 if (n == null)
2034 throw new NoSuchElementException();
2035 return n.key;
2036 }
2037
2038 /**
2039 * Returns the last (highest) key currently in this map.
2040 *
2041 * @return the last (highest) key currently in this map.
2042 * @throws NoSuchElementException Map is empty.
2043 */
2044 public K lastKey() {
2045 Node<K,V> n = findLast();
2046 if (n == null)
2047 throw new NoSuchElementException();
2048 return n.key;
2049 }
2050
2051 /**
2052 * Returns a view of the portion of this map whose keys range from
2053 * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
2054 * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
2055 * is empty.) The returned sorted map is backed by this map, so changes
2056 * in the returned sorted map are reflected in this map, and vice-versa.
2057
2058 * @param fromKey low endpoint (inclusive) of the subMap.
2059 * @param toKey high endpoint (exclusive) of the subMap.
2060 *
2061 * @return a view of the portion of this map whose keys range from
2062 * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
2063 *
2064 * @throws ClassCastException if <tt>fromKey</tt> and <tt>toKey</tt>
2065 * cannot be compared to one another using this map's comparator
2066 * (or, if the map has no comparator, using natural ordering).
2067 * @throws IllegalArgumentException if <tt>fromKey</tt> is greater than
2068 * <tt>toKey</tt>.
2069 * @throws NullPointerException if <tt>fromKey</tt> or <tt>toKey</tt> is
2070 * <tt>null</tt>.
2071 */
2072 public ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey) {
2073 if (fromKey == null || toKey == null)
2074 throw new NullPointerException();
2075 return new ConcurrentSkipListSubMap(this, fromKey, toKey);
2076 }
2077
2078 /**
2079 * Returns a view of the portion of this map whose keys are strictly less
2080 * than <tt>toKey</tt>. The returned sorted map is backed by this map, so
2081 * changes in the returned sorted map are reflected in this map, and
2082 * vice-versa.
2083 * @param toKey high endpoint (exclusive) of the headMap.
2084 * @return a view of the portion of this map whose keys are strictly
2085 * less than <tt>toKey</tt>.
2086 *
2087 * @throws ClassCastException if <tt>toKey</tt> is not compatible
2088 * with this map's comparator (or, if the map has no comparator,
2089 * if <tt>toKey</tt> does not implement <tt>Comparable</tt>).
2090 * @throws NullPointerException if <tt>toKey</tt> is <tt>null</tt>.
2091 */
2092 public ConcurrentNavigableMap<K,V> headMap(K toKey) {
2093 if (toKey == null)
2094 throw new NullPointerException();
2095 return new ConcurrentSkipListSubMap(this, null, toKey);
2096 }
2097
2098 /**
2099 * Returns a view of the portion of this map whose keys are
2100 * greater than or equal to <tt>fromKey</tt>. The returned sorted
2101 * map is backed by this map, so changes in the returned sorted
2102 * map are reflected in this map, and vice-versa.
2103 * @param fromKey low endpoint (inclusive) of the tailMap.
2104 * @return a view of the portion of this map whose keys are greater
2105 * than or equal to <tt>fromKey</tt>.
2106 * @throws ClassCastException if <tt>fromKey</tt> is not compatible
2107 * with this map's comparator (or, if the map has no comparator,
2108 * if <tt>fromKey</tt> does not implement <tt>Comparable</tt>).
2109 * @throws NullPointerException if <tt>fromKey</tt> is <tt>null</tt>.
2110 */
2111 public ConcurrentNavigableMap<K,V> tailMap(K fromKey) {
2112 if (fromKey == null)
2113 throw new NullPointerException();
2114 return new ConcurrentSkipListSubMap(this, fromKey, null);
2115 }
2116
2117 /* ---------------- Relational operations -------------- */
2118
2119 /**
2120 * Returns a key-value mapping associated with the least key
2121 * greater than or equal to the given key, or <tt>null</tt> if there is
2122 * no such entry. The returned entry does <em>not</em> support
2123 * the <tt>Entry.setValue</tt> method.
2124 *
2125 * @param key the key.
2126 * @return an Entry associated with ceiling of given key, or <tt>null</tt>
2127 * if there is no such Entry.
2128 * @throws ClassCastException if key cannot be compared with the keys
2129 * currently in the map.
2130 * @throws NullPointerException if key is <tt>null</tt>.
2131 */
2132 public Map.Entry<K,V> ceilingEntry(K key) {
2133 return getNear(key, GT|EQ);
2134 }
2135
2136 /**
2137 * Returns a key-value mapping associated with the greatest
2138 * key strictly less than the given key, or <tt>null</tt> if there is no
2139 * such entry. The returned entry does <em>not</em> support
2140 * the <tt>Entry.setValue</tt> method.
2141 *
2142 * @param key the key.
2143 * @return an Entry with greatest key less than the given
2144 * key, or <tt>null</tt> if there is no such Entry.
2145 * @throws ClassCastException if key cannot be compared with the keys
2146 * currently in the map.
2147 * @throws NullPointerException if key is <tt>null</tt>.
2148 */
2149 public Map.Entry<K,V> lowerEntry(K key) {
2150 return getNear(key, LT);
2151 }
2152
2153 /**
2154 * Returns a key-value mapping associated with the greatest
2155 * key less than or equal to the given key, or <tt>null</tt> if there is no
2156 * such entry. The returned entry does <em>not</em> support
2157 * the <tt>Entry.setValue</tt> method.
2158 *
2159 * @param key the key.
2160 * @return an Entry associated with floor of given key, or <tt>null</tt>
2161 * if there is no such Entry.
2162 * @throws ClassCastException if key cannot be compared with the keys
2163 * currently in the map.
2164 * @throws NullPointerException if key is <tt>null</tt>.
2165 */
2166 public Map.Entry<K,V> floorEntry(K key) {
2167 return getNear(key, LT|EQ);
2168 }
2169
2170 /**
2171 * Returns a key-value mapping associated with the least
2172 * key strictly greater than the given key, or <tt>null</tt> if there is no
2173 * such entry. The returned entry does <em>not</em> support
2174 * the <tt>Entry.setValue</tt> method.
2175 *
2176 * @param key the key.
2177 * @return an Entry with least key greater than the given key, or
2178 * <tt>null</tt> if there is no such Entry.
2179 * @throws ClassCastException if key cannot be compared with the keys
2180 * currently in the map.
2181 * @throws NullPointerException if key is <tt>null</tt>.
2182 */
2183 public Map.Entry<K,V> higherEntry(K key) {
2184 return getNear(key, GT);
2185 }
2186
2187 /**
2188 * Returns a key-value mapping associated with the least
2189 * key in this map, or <tt>null</tt> if the map is empty.
2190 * The returned entry does <em>not</em> support
2191 * the <tt>Entry.setValue</tt> method.
2192 *
2193 * @return an Entry with least key, or <tt>null</tt>
2194 * if the map is empty.
2195 */
2196 public Map.Entry<K,V> firstEntry() {
2197 for (;;) {
2198 Node<K,V> n = findFirst();
2199 if (n == null)
2200 return null;
2201 SnapshotEntry<K,V> e = n.createSnapshot();
2202 if (e != null)
2203 return e;
2204 }
2205 }
2206
2207 /**
2208 * Returns a key-value mapping associated with the greatest
2209 * key in this map, or <tt>null</tt> if the map is empty.
2210 * The returned entry does <em>not</em> support
2211 * the <tt>Entry.setValue</tt> method.
2212 *
2213 * @return an Entry with greatest key, or <tt>null</tt>
2214 * if the map is empty.
2215 */
2216 public Map.Entry<K,V> lastEntry() {
2217 for (;;) {
2218 Node<K,V> n = findLast();
2219 if (n == null)
2220 return null;
2221 SnapshotEntry<K,V> e = n.createSnapshot();
2222 if (e != null)
2223 return e;
2224 }
2225 }
2226
2227 /**
2228 * Removes and returns a key-value mapping associated with
2229 * the least key in this map, or <tt>null</tt> if the map is empty.
2230 * The returned entry does <em>not</em> support
2231 * the <tt>Entry.setValue</tt> method.
2232 *
2233 * @return the removed first entry of this map, or <tt>null</tt>
2234 * if the map is empty.
2235 */
2236 public Map.Entry<K,V> pollFirstEntry() {
2237 return doRemoveFirstEntry();
2238 }
2239
2240 /**
2241 * Removes and returns a key-value mapping associated with
2242 * the greatest key in this map, or <tt>null</tt> if the map is empty.
2243 * The returned entry does <em>not</em> support
2244 * the <tt>Entry.setValue</tt> method.
2245 *
2246 * @return the removed last entry of this map, or <tt>null</tt>
2247 * if the map is empty.
2248 */
2249 public Map.Entry<K,V> pollLastEntry() {
2250 return doRemoveLastEntry();
2251 }
2252
2253 /* ---------------- Iterators -------------- */
2254
2255 /**
2256 * Base of iterator classes.
2257 * (Six kinds: {key, value, entry} X {map, submap})
2258 */
2259 abstract class ConcurrentSkipListMapIterator {
2260 /** the last node returned by next() */
2261 Node<K,V> last;
2262 /** the next node to return from next(); */
2263 Node<K,V> next;
2264 /** Cache of next value field to maintain weak consistency */
2265 Object nextValue;
2266
2267 /** Create normal iterator for entire range */
2268 ConcurrentSkipListMapIterator() {
2269 for (;;) {
2270 next = findFirst();
2271 if (next == null)
2272 break;
2273 nextValue = next.value;
2274 if (nextValue != null && nextValue != next)
2275 break;
2276 }
2277 }
2278
2279 /**
2280 * Create a submap iterator starting at given least key, or
2281 * first node if least is <tt>null</tt>, but not greater or equal to
2282 * fence, or end if fence is <tt>null</tt>.
2283 */
2284 ConcurrentSkipListMapIterator(K least, K fence) {
2285 for (;;) {
2286 next = findCeiling(least);
2287 if (next == null)
2288 break;
2289 nextValue = next.value;
2290 if (nextValue != null && nextValue != next) {
2291 if (fence != null && compare(fence, next.key) <= 0) {
2292 next = null;
2293 nextValue = null;
2294 }
2295 break;
2296 }
2297 }
2298 }
2299
2300 public final boolean hasNext() {
2301 return next != null;
2302 }
2303
2304 final void advance() {
2305 if ((last = next) == null)
2306 throw new NoSuchElementException();
2307 for (;;) {
2308 next = next.next;
2309 if (next == null)
2310 break;
2311 nextValue = next.value;
2312 if (nextValue != null && nextValue != next)
2313 break;
2314 }
2315 }
2316
2317 /**
2318 * Version of advance for submaps to stop at fence
2319 */
2320 final void advance(K fence) {
2321 if ((last = next) == null)
2322 throw new NoSuchElementException();
2323 for (;;) {
2324 next = next.next;
2325 if (next == null)
2326 break;
2327 nextValue = next.value;
2328 if (nextValue != null && nextValue != next) {
2329 if (fence != null && compare(fence, next.key) <= 0) {
2330 next = null;
2331 nextValue = null;
2332 }
2333 break;
2334 }
2335 }
2336 }
2337
2338 public void remove() {
2339 Node<K,V> l = last;
2340 if (l == null)
2341 throw new IllegalStateException();
2342 // It would not be worth all of the overhead to directly
2343 // unlink from here. Using remove is fast enough.
2344 ConcurrentSkipListMap.this.remove(l.key);
2345 }
2346 }
2347
2348 final class ValueIterator extends ConcurrentSkipListMapIterator
2349 implements Iterator<V> {
2350 public V next() {
2351 Object v = nextValue;
2352 advance();
2353 return (V)v;
2354 }
2355 }
2356
2357 final class KeyIterator extends ConcurrentSkipListMapIterator
2358 implements Iterator<K> {
2359 public K next() {
2360 Node<K,V> n = next;
2361 advance();
2362 return n.key;
2363 }
2364 }
2365
2366 /**
2367 * Entry iterators use the same trick as in ConcurrentHashMap and
2368 * elsewhere of using the iterator itself to represent entries,
2369 * thus avoiding having to create entry objects in next().
2370 */
2371 class EntryIterator extends ConcurrentSkipListMapIterator
2372 implements Map.Entry<K,V>, Iterator<Map.Entry<K,V>> {
2373 /** Cache of last value returned */
2374 Object lastValue;
2375
2376 EntryIterator() {
2377 super();
2378 }
2379
2380 EntryIterator(K least, K fence) {
2381 super(least, fence);
2382 }
2383
2384 public Map.Entry<K,V> next() {
2385 lastValue = nextValue;
2386 advance();
2387 return this;
2388 }
2389
2390 public K getKey() {
2391 Node<K,V> l = last;
2392 if (l == null)
2393 throw new IllegalStateException();
2394 return l.key;
2395 }
2396
2397 public V getValue() {
2398 Object v = lastValue;
2399 if (last == null || v == null)
2400 throw new IllegalStateException();
2401 return (V)v;
2402 }
2403
2404 public V setValue(V value) {
2405 throw new UnsupportedOperationException();
2406 }
2407
2408 public boolean equals(Object o) {
2409 // If not acting as entry, just use default.
2410 if (last == null)
2411 return super.equals(o);
2412 if (!(o instanceof Map.Entry))
2413 return false;
2414 Map.Entry e = (Map.Entry)o;
2415 return (getKey().equals(e.getKey()) &&
2416 getValue().equals(e.getValue()));
2417 }
2418
2419 public int hashCode() {
2420 // If not acting as entry, just use default.
2421 if (last == null)
2422 return super.hashCode();
2423 return getKey().hashCode() ^ getValue().hashCode();
2424 }
2425
2426 public String toString() {
2427 // If not acting as entry, just use default.
2428 if (last == null)
2429 return super.toString();
2430 return getKey() + "=" + getValue();
2431 }
2432 }
2433
2434 /**
2435 * Submap iterators start at given starting point at beginning of
2436 * submap range, and advance until they are at end of range.
2437 */
2438 class SubMapEntryIterator extends EntryIterator {
2439 final K fence;
2440 SubMapEntryIterator(K least, K fence) {
2441 super(least, fence);
2442 this.fence = fence;
2443 }
2444
2445 public Map.Entry<K,V> next() {
2446 lastValue = nextValue;
2447 advance(fence);
2448 return this;
2449 }
2450 }
2451
2452 class SubMapValueIterator extends ConcurrentSkipListMapIterator
2453 implements Iterator<V> {
2454 final K fence;
2455 SubMapValueIterator(K least, K fence) {
2456 super(least, fence);
2457 this.fence = fence;
2458 }
2459
2460 public V next() {
2461 Object v = nextValue;
2462 advance(fence);
2463 return (V)v;
2464 }
2465 }
2466
2467 class SubMapKeyIterator extends ConcurrentSkipListMapIterator
2468 implements Iterator<K> {
2469 final K fence;
2470 SubMapKeyIterator(K least, K fence) {
2471 super(least, fence);
2472 this.fence = fence;
2473 }
2474
2475 public K next() {
2476 Node<K,V> n = next;
2477 advance(fence);
2478 return n.key;
2479 }
2480 }
2481
2482 /* ---------------- Utilities for views, sets, submaps -------------- */
2483
2484 // Factory methods for iterators needed by submaps and/or
2485 // ConcurrentSkipListSet
2486
2487 Iterator<K> keyIterator() {
2488 return new KeyIterator();
2489 }
2490
2491 SubMapEntryIterator subMapEntryIterator(K least, K fence) {
2492 return new SubMapEntryIterator(least, fence);
2493 }
2494
2495 SubMapKeyIterator subMapKeyIterator(K least, K fence) {
2496 return new SubMapKeyIterator(least, fence);
2497 }
2498
2499 SubMapValueIterator subMapValueIterator(K least, K fence) {
2500 return new SubMapValueIterator(least, fence);
2501 }
2502
2503
2504 /**
2505 * Version of remove with boolean return. Needed by
2506 * view classes and ConcurrentSkipListSet
2507 */
2508 boolean removep(Object key) {
2509 return doRemove(key, null) != null;
2510 }
2511
2512 /**
2513 * Return SnapshotEntry for results of findNear ofter screening
2514 * to ensure result is in given range. Needed by submaps.
2515 * @param kkey the key
2516 * @param rel the relation -- OR'ed combination of EQ, LT, GT
2517 * @param least minimum allowed key value
2518 * @param fence key greater than maximum allowed key value
2519 * @return Entry fitting relation, or <tt>null</tt> if no such
2520 */
2521 SnapshotEntry<K,V> getNear(K kkey, int rel, K least, K fence) {
2522 K key = kkey;
2523 // Don't return keys less than least
2524 if ((rel & LT) == 0) {
2525 if (compare(key, least) < 0) {
2526 key = least;
2527 rel = rel | EQ;
2528 }
2529 }
2530
2531 for (;;) {
2532 Node<K,V> n = findNear(key, rel);
2533 if (n == null || !inHalfOpenRange(n.key, least, fence))
2534 return null;
2535 SnapshotEntry<K,V> e = n.createSnapshot();
2536 if (e != null)
2537 return e;
2538 }
2539 }
2540
2541 // Methods expanding out relational operations for submaps
2542
2543 /**
2544 * Return ceiling, or first node if key is <tt>null</tt>
2545 */
2546 Node<K,V> findCeiling(K key) {
2547 return (key == null)? findFirst() : findNear(key, GT|EQ);
2548 }
2549
2550 /**
2551 * Return lower node, or last node if key is <tt>null</tt>
2552 */
2553 Node<K,V> findLower(K key) {
2554 return (key == null)? findLast() : findNear(key, LT);
2555 }
2556
2557 /**
2558 * Find and remove least element of subrange.
2559 */
2560 SnapshotEntry<K,V> removeFirstEntryOfSubrange(K least, K fence) {
2561 for (;;) {
2562 Node<K,V> n = findCeiling(least);
2563 if (n == null)
2564 return null;
2565 K k = n.key;
2566 if (fence != null && compare(k, fence) >= 0)
2567 return null;
2568 V v = doRemove(k, null);
2569 if (v != null)
2570 return new SnapshotEntry<K,V>(k,v);
2571 }
2572 }
2573
2574
2575 /**
2576 * Find and remove greatest element of subrange.
2577 */
2578 SnapshotEntry<K,V> removeLastEntryOfSubrange(K least, K fence) {
2579 for (;;) {
2580 Node<K,V> n = findLower(fence);
2581 if (n == null)
2582 return null;
2583 K k = n.key;
2584 if (least != null && compare(k, least) < 0)
2585 return null;
2586 V v = doRemove(k, null);
2587 if (v != null)
2588 return new SnapshotEntry<K,V>(k,v);
2589 }
2590 }
2591
2592
2593 SnapshotEntry<K,V> getCeiling(K key, K least, K fence) {
2594 return getNear(key, GT|EQ, least, fence);
2595 }
2596
2597 SnapshotEntry<K,V> getLower(K key, K least, K fence) {
2598 return getNear(key, LT, least, fence);
2599 }
2600
2601 SnapshotEntry<K,V> getFloor(K key, K least, K fence) {
2602 return getNear(key, LT|EQ, least, fence);
2603 }
2604
2605 SnapshotEntry<K,V> getHigher(K key, K least, K fence) {
2606 return getNear(key, GT, least, fence);
2607 }
2608
2609 // Key-returning relational methods for ConcurrentSkipListSet
2610
2611 K ceilingKey(K key) {
2612 Node<K,V> n = findNear(key, GT|EQ);
2613 return (n == null)? null : n.key;
2614 }
2615
2616 K lowerKey(K key) {
2617 Node<K,V> n = findNear(key, LT);
2618 return (n == null)? null : n.key;
2619 }
2620
2621 K floorKey(K key) {
2622 Node<K,V> n = findNear(key, LT|EQ);
2623 return (n == null)? null : n.key;
2624 }
2625
2626 K higherKey(K key) {
2627 Node<K,V> n = findNear(key, GT);
2628 return (n == null)? null : n.key;
2629 }
2630
2631 K lowestKey() {
2632 Node<K,V> n = findFirst();
2633 return (n == null)? null : n.key;
2634 }
2635
2636 K highestKey() {
2637 Node<K,V> n = findLast();
2638 return (n == null)? null : n.key;
2639 }
2640
2641 /* ---------------- Views -------------- */
2642
2643 final class KeySet extends AbstractSet<K> {
2644 public Iterator<K> iterator() {
2645 return new KeyIterator();
2646 }
2647 public boolean isEmpty() {
2648 return ConcurrentSkipListMap.this.isEmpty();
2649 }
2650 public int size() {
2651 return ConcurrentSkipListMap.this.size();
2652 }
2653 public boolean contains(Object o) {
2654 return ConcurrentSkipListMap.this.containsKey(o);
2655 }
2656 public boolean remove(Object o) {
2657 return ConcurrentSkipListMap.this.removep(o);
2658 }
2659 public void clear() {
2660 ConcurrentSkipListMap.this.clear();
2661 }
2662 public Object[] toArray() {
2663 Collection<K> c = new ArrayList<K>();
2664 for (Iterator<K> i = iterator(); i.hasNext(); )
2665 c.add(i.next());
2666 return c.toArray();
2667 }
2668 public <T> T[] toArray(T[] a) {
2669 Collection<K> c = new ArrayList<K>();
2670 for (Iterator<K> i = iterator(); i.hasNext(); )
2671 c.add(i.next());
2672 return c.toArray(a);
2673 }
2674 }
2675
2676
2677 final class Values extends AbstractCollection<V> {
2678 public Iterator<V> iterator() {
2679 return new ValueIterator();
2680 }
2681 public boolean isEmpty() {
2682 return ConcurrentSkipListMap.this.isEmpty();
2683 }
2684 public int size() {
2685 return ConcurrentSkipListMap.this.size();
2686 }
2687 public boolean contains(Object o) {
2688 return ConcurrentSkipListMap.this.containsValue(o);
2689 }
2690 public void clear() {
2691 ConcurrentSkipListMap.this.clear();
2692 }
2693 public Object[] toArray() {
2694 Collection<V> c = new ArrayList<V>();
2695 for (Iterator<V> i = iterator(); i.hasNext(); )
2696 c.add(i.next());
2697 return c.toArray();
2698 }
2699 public <T> T[] toArray(T[] a) {
2700 Collection<V> c = new ArrayList<V>();
2701 for (Iterator<V> i = iterator(); i.hasNext(); )
2702 c.add(i.next());
2703 return c.toArray(a);
2704 }
2705 }
2706
2707 final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
2708 public Iterator<Map.Entry<K,V>> iterator() {
2709 return new EntryIterator();
2710 }
2711 public boolean contains(Object o) {
2712 if (!(o instanceof Map.Entry))
2713 return false;
2714 Map.Entry<K,V> e = (Map.Entry<K,V>)o;
2715 V v = ConcurrentSkipListMap.this.get(e.getKey());
2716 return v != null && v.equals(e.getValue());
2717 }
2718 public boolean remove(Object o) {
2719 if (!(o instanceof Map.Entry))
2720 return false;
2721 Map.Entry<K,V> e = (Map.Entry<K,V>)o;
2722 return ConcurrentSkipListMap.this.remove(e.getKey(), e.getValue());
2723 }
2724 public boolean isEmpty() {
2725 return ConcurrentSkipListMap.this.isEmpty();
2726 }
2727 public int size() {
2728 return ConcurrentSkipListMap.this.size();
2729 }
2730 public void clear() {
2731 ConcurrentSkipListMap.this.clear();
2732 }
2733
2734 public Object[] toArray() {
2735 Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
2736 for (Node<K,V> n = findFirst(); n != null; n = n.next) {
2737 Map.Entry<K,V> e = n.createSnapshot();
2738 if (e != null)
2739 c.add(e);
2740 }
2741 return c.toArray();
2742 }
2743 public <T> T[] toArray(T[] a) {
2744 Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
2745 for (Node<K,V> n = findFirst(); n != null; n = n.next) {
2746 Map.Entry<K,V> e = n.createSnapshot();
2747 if (e != null)
2748 c.add(e);
2749 }
2750 return c.toArray(a);
2751 }
2752 }
2753
2754 /**
2755 * Submaps returned by {@link ConcurrentSkipListMap} submap operations
2756 * represent a subrange of mappings of their underlying
2757 * maps. Instances of this class support all methods of their
2758 * underlying maps, differing in that mappings outside their range are
2759 * ignored, and attempts to add mappings outside their ranges result
2760 * in {@link IllegalArgumentException}. Instances of this class are
2761 * constructed only using the <tt>subMap</tt>, <tt>headMap</tt>, and
2762 * <tt>tailMap</tt> methods of their underlying maps.
2763 */
2764 static class ConcurrentSkipListSubMap<K,V> extends AbstractMap<K,V>
2765 implements ConcurrentNavigableMap<K,V>, java.io.Serializable {
2766
2767 private static final long serialVersionUID = -7647078645895051609L;
2768
2769 /** Underlying map */
2770 private final ConcurrentSkipListMap<K,V> m;
2771 /** lower bound key, or null if from start */
2772 private final K least;
2773 /** upper fence key, or null if to end */
2774 private final K fence;
2775 // Lazily initialized view holders
2776 private transient Set<K> keySetView;
2777 private transient Set<Map.Entry<K,V>> entrySetView;
2778 private transient Collection<V> valuesView;
2779
2780 /**
2781 * Creates a new submap.
2782 * @param least inclusive least value, or <tt>null</tt> if from start
2783 * @param fence exclusive upper bound or <tt>null</tt> if to end
2784 * @throws IllegalArgumentException if least and fence nonnull
2785 * and least greater than fence
2786 */
2787 ConcurrentSkipListSubMap(ConcurrentSkipListMap<K,V> map,
2788 K least, K fence) {
2789 if (least != null && fence != null && map.compare(least, fence) > 0)
2790 throw new IllegalArgumentException("inconsistent range");
2791 this.m = map;
2792 this.least = least;
2793 this.fence = fence;
2794 }
2795
2796 /* ---------------- Utilities -------------- */
2797
2798 boolean inHalfOpenRange(K key) {
2799 return m.inHalfOpenRange(key, least, fence);
2800 }
2801
2802 boolean inOpenRange(K key) {
2803 return m.inOpenRange(key, least, fence);
2804 }
2805
2806 ConcurrentSkipListMap.Node<K,V> firstNode() {
2807 return m.findCeiling(least);
2808 }
2809
2810 ConcurrentSkipListMap.Node<K,V> lastNode() {
2811 return m.findLower(fence);
2812 }
2813
2814 boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
2815 return (n != null &&
2816 (fence == null ||
2817 n.key == null || // pass by markers and headers
2818 m.compare(fence, n.key) > 0));
2819 }
2820
2821 void checkKey(K key) throws IllegalArgumentException {
2822 if (!inHalfOpenRange(key))
2823 throw new IllegalArgumentException("key out of range");
2824 }
2825
2826 /**
2827 * Returns underlying map. Needed by ConcurrentSkipListSet
2828 * @return the backing map
2829 */
2830 ConcurrentSkipListMap<K,V> getMap() {
2831 return m;
2832 }
2833
2834 /**
2835 * Returns least key. Needed by ConcurrentSkipListSet
2836 * @return least key or <tt>null</tt> if from start
2837 */
2838 K getLeast() {
2839 return least;
2840 }
2841
2842 /**
2843 * Returns fence key. Needed by ConcurrentSkipListSet
2844 * @return fence key or <tt>null</tt> of to end
2845 */
2846 K getFence() {
2847 return fence;
2848 }
2849
2850 /**
2851 * Non-exception throwing version of firstKey needed by
2852 * ConcurrentSkipListSubSet
2853 * @return first key, or <tt>null</tt> if empty
2854 */
2855 K lowestKey() {
2856 ConcurrentSkipListMap.Node<K,V> n = firstNode();
2857 if (isBeforeEnd(n))
2858 return n.key;
2859 else
2860 return null;
2861 }
2862
2863 /**
2864 * Non-exception throwing version of highestKey needed by
2865 * ConcurrentSkipListSubSet
2866 * @return last key, or <tt>null</tt> if empty
2867 */
2868 K highestKey() {
2869 ConcurrentSkipListMap.Node<K,V> n = lastNode();
2870 if (isBeforeEnd(n))
2871 return n.key;
2872 else
2873 return null;
2874 }
2875
2876 /* ---------------- Map API methods -------------- */
2877
2878 /**
2879 * Returns <tt>true</tt> if this map contains a mapping for
2880 * the specified key.
2881 * @param key key whose presence in this map is to be tested.
2882 * @return <tt>true</tt> if this map contains a mapping for
2883 * the specified key.
2884 * @throws ClassCastException if the key cannot be compared
2885 * with the keys currently in the map.
2886 * @throws NullPointerException if the key is <tt>null</tt>.
2887 */
2888 public boolean containsKey(Object key) {
2889 K k = (K)key;
2890 return inHalfOpenRange(k) && m.containsKey(k);
2891 }
2892
2893 /**
2894 * Returns the value to which this map maps the specified key.
2895 * Returns <tt>null</tt> if the map contains no mapping for
2896 * this key.
2897 *
2898 * @param key key whose associated value is to be returned.
2899 * @return the value to which this map maps the specified key,
2900 * or <tt>null</tt> if the map contains no mapping for the
2901 * key.
2902 * @throws ClassCastException if the key cannot be compared
2903 * with the keys currently in the map.
2904 * @throws NullPointerException if the key is <tt>null</tt>.
2905 */
2906 public V get(Object key) {
2907 K k = (K)key;
2908 return ((!inHalfOpenRange(k)) ? null : m.get(k));
2909 }
2910
2911 /**
2912 * Associates the specified value with the specified key in
2913 * this map. If the map previously contained a mapping for
2914 * this key, the old value is replaced.
2915 *
2916 * @param key key with which the specified value is to be associated.
2917 * @param value value to be associated with the specified key.
2918 *
2919 * @return previous value associated with specified key, or
2920 * <tt>null</tt> if there was no mapping for key.
2921 * @throws ClassCastException if the key cannot be compared
2922 * with the keys currently in the map.
2923 * @throws IllegalArgumentException if key outside range of
2924 * this submap.
2925 * @throws NullPointerException if the key or value are <tt>null</tt>.
2926 */
2927 public V put(K key, V value) {
2928 checkKey(key);
2929 return m.put(key, value);
2930 }
2931
2932 /**
2933 * Removes the mapping for this key from this Map if present.
2934 *
2935 * @param key key for which mapping should be removed
2936 * @return previous value associated with specified key, or
2937 * <tt>null</tt> if there was no mapping for key.
2938 *
2939 * @throws ClassCastException if the key cannot be compared
2940 * with the keys currently in the map.
2941 * @throws NullPointerException if the key is <tt>null</tt>.
2942 */
2943 public V remove(Object key) {
2944 K k = (K)key;
2945 return (!inHalfOpenRange(k))? null : m.remove(k);
2946 }
2947
2948 /**
2949 * Returns the number of elements in this map. If this map
2950 * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
2951 * returns <tt>Integer.MAX_VALUE</tt>.
2952 *
2953 * <p>Beware that, unlike in most collections, this method is
2954 * <em>NOT</em> a constant-time operation. Because of the
2955 * asynchronous nature of these maps, determining the current
2956 * number of elements requires traversing them all to count them.
2957 * Additionally, it is possible for the size to change during
2958 * execution of this method, in which case the returned result
2959 * will be inaccurate. Thus, this method is typically not very
2960 * useful in concurrent applications.
2961 *
2962 * @return the number of elements in this map.
2963 */
2964 public int size() {
2965 long count = 0;
2966 for (ConcurrentSkipListMap.Node<K,V> n = firstNode();
2967 isBeforeEnd(n);
2968 n = n.next) {
2969 if (n.getValidValue() != null)
2970 ++count;
2971 }
2972 return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count;
2973 }
2974
2975 /**
2976 * Returns <tt>true</tt> if this map contains no key-value mappings.
2977 * @return <tt>true</tt> if this map contains no key-value mappings.
2978 */
2979 public boolean isEmpty() {
2980 return !isBeforeEnd(firstNode());
2981 }
2982
2983 /**
2984 * Returns <tt>true</tt> if this map maps one or more keys to the
2985 * specified value. This operation requires time linear in the
2986 * Map size.
2987 *
2988 * @param value value whose presence in this Map is to be tested.
2989 * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
2990 * <tt>false</tt> otherwise.
2991 * @throws NullPointerException if the value is <tt>null</tt>.
2992 */
2993 public boolean containsValue(Object value) {
2994 if (value == null)
2995 throw new NullPointerException();
2996 for (ConcurrentSkipListMap.Node<K,V> n = firstNode();
2997 isBeforeEnd(n);
2998 n = n.next) {
2999 V v = n.getValidValue();
3000 if (v != null && value.equals(v))
3001 return true;
3002 }
3003 return false;
3004 }
3005
3006 /**
3007 * Removes all mappings from this map.
3008 */
3009 public void clear() {
3010 for (ConcurrentSkipListMap.Node<K,V> n = firstNode();
3011 isBeforeEnd(n);
3012 n = n.next) {
3013 if (n.getValidValue() != null)
3014 m.remove(n.key);
3015 }
3016 }
3017
3018 /* ---------------- ConcurrentMap API methods -------------- */
3019
3020 /**
3021 * If the specified key is not already associated
3022 * with a value, associate it with the given value.
3023 * This is equivalent to
3024 * <pre>
3025 * if (!map.containsKey(key))
3026 * return map.put(key, value);
3027 * else
3028 * return map.get(key);
3029 * </pre>
3030 * Except that the action is performed atomically.
3031 * @param key key with which the specified value is to be associated.
3032 * @param value value to be associated with the specified key.
3033 * @return previous value associated with specified key, or
3034 * <tt>null</tt> if there was no mapping for key.
3035 *
3036 * @throws ClassCastException if the key cannot be compared
3037 * with the keys currently in the map.
3038 * @throws IllegalArgumentException if key outside range of
3039 * this submap.
3040 * @throws NullPointerException if the key or value are <tt>null</tt>.
3041 */
3042 public V putIfAbsent(K key, V value) {
3043 checkKey(key);
3044 return m.putIfAbsent(key, value);
3045 }
3046
3047 /**
3048 * Remove entry for key only if currently mapped to given value.
3049 * Acts as
3050 * <pre>
3051 * if ((map.containsKey(key) && map.get(key).equals(value)) {
3052 * map.remove(key);
3053 * return true;
3054 * } else return false;
3055 * </pre>
3056 * except that the action is performed atomically.
3057 * @param key key with which the specified value is associated.
3058 * @param value value associated with the specified key.
3059 * @return true if the value was removed, false otherwise
3060 * @throws ClassCastException if the key cannot be compared
3061 * with the keys currently in the map.
3062 * @throws NullPointerException if the key or value are
3063 * <tt>null</tt>.
3064 */
3065 public boolean remove(Object key, Object value) {
3066 K k = (K)key;
3067 return inHalfOpenRange(k) && m.remove(k, value);
3068 }
3069
3070 /**
3071 * Replace entry for key only if currently mapped to given value.
3072 * Acts as
3073 * <pre>
3074 * if ((map.containsKey(key) && map.get(key).equals(oldValue)) {
3075 * map.put(key, newValue);
3076 * return true;
3077 * } else return false;
3078 * </pre>
3079 * except that the action is performed atomically.
3080 * @param key key with which the specified value is associated.
3081 * @param oldValue value expected to be associated with the specified key.
3082 * @param newValue value to be associated with the specified key.
3083 * @return true if the value was replaced
3084 * @throws ClassCastException if the key cannot be compared
3085 * with the keys currently in the map.
3086 * @throws IllegalArgumentException if key outside range of
3087 * this submap.
3088 * @throws NullPointerException if key, oldValue or newValue
3089 * are <tt>null</tt>.
3090 */
3091 public boolean replace(K key, V oldValue, V newValue) {
3092 checkKey(key);
3093 return m.replace(key, oldValue, newValue);
3094 }
3095
3096 /**
3097 * Replace entry for key only if currently mapped to some value.
3098 * Acts as
3099 * <pre>
3100 * if ((map.containsKey(key)) {
3101 * return map.put(key, value);
3102 * } else return null;
3103 * </pre>
3104 * except that the action is performed atomically.
3105 * @param key key with which the specified value is associated.
3106 * @param value value to be associated with the specified key.
3107 * @return previous value associated with specified key, or
3108 * <tt>null</tt> if there was no mapping for key.
3109 * @throws ClassCastException if the key cannot be compared
3110 * with the keys currently in the map.
3111 * @throws IllegalArgumentException if key outside range of
3112 * this submap.
3113 * @throws NullPointerException if the key or value are
3114 * <tt>null</tt>.
3115 */
3116 public V replace(K key, V value) {
3117 checkKey(key);
3118 return m.replace(key, value);
3119 }
3120
3121 /* ---------------- SortedMap API methods -------------- */
3122
3123 /**
3124 * Returns the comparator used to order this map, or <tt>null</tt>
3125 * if this map uses its keys' natural order.
3126 *
3127 * @return the comparator associated with this map, or
3128 * <tt>null</tt> if it uses its keys' natural sort method.
3129 */
3130 public Comparator<? super K> comparator() {
3131 return m.comparator();
3132 }
3133
3134 /**
3135 * Returns the first (lowest) key currently in this map.
3136 *
3137 * @return the first (lowest) key currently in this map.
3138 * @throws NoSuchElementException Map is empty.
3139 */
3140 public K firstKey() {
3141 ConcurrentSkipListMap.Node<K,V> n = firstNode();
3142 if (isBeforeEnd(n))
3143 return n.key;
3144 else
3145 throw new NoSuchElementException();
3146 }
3147
3148 /**
3149 * Returns the last (highest) key currently in this map.
3150 *
3151 * @return the last (highest) key currently in this map.
3152 * @throws NoSuchElementException Map is empty.
3153 */
3154 public K lastKey() {
3155 ConcurrentSkipListMap.Node<K,V> n = lastNode();
3156 if (n != null) {
3157 K last = n.key;
3158 if (inHalfOpenRange(last))
3159 return last;
3160 }
3161 throw new NoSuchElementException();
3162 }
3163
3164 /**
3165 * Returns a view of the portion of this map whose keys range
3166 * from <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>,
3167 * exclusive. (If <tt>fromKey</tt> and <tt>toKey</tt> are
3168 * equal, the returned sorted map is empty.) The returned
3169 * sorted map is backed by this map, so changes in the
3170 * returned sorted map are reflected in this map, and
3171 * vice-versa.
3172
3173 * @param fromKey low endpoint (inclusive) of the subMap.
3174 * @param toKey high endpoint (exclusive) of the subMap.
3175 *
3176 * @return a view of the portion of this map whose keys range
3177 * from <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>,
3178 * exclusive.
3179 *
3180 * @throws ClassCastException if <tt>fromKey</tt> and
3181 * <tt>toKey</tt> cannot be compared to one another using this
3182 * map's comparator (or, if the map has no comparator, using
3183 * natural ordering).
3184 * @throws IllegalArgumentException if <tt>fromKey</tt> is
3185 * greater than <tt>toKey</tt> or either key is outside of
3186 * the range of this submap.
3187 * @throws NullPointerException if <tt>fromKey</tt> or
3188 * <tt>toKey</tt> is <tt>null</tt>.
3189 */
3190 public ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey) {
3191 if (fromKey == null || toKey == null)
3192 throw new NullPointerException();
3193 if (!inOpenRange(fromKey) || !inOpenRange(toKey))
3194 throw new IllegalArgumentException("key out of range");
3195 return new ConcurrentSkipListSubMap(m, fromKey, toKey);
3196 }
3197
3198 /**
3199 * Returns a view of the portion of this map whose keys are
3200 * strictly less than <tt>toKey</tt>. The returned sorted map
3201 * is backed by this map, so changes in the returned sorted
3202 * map are reflected in this map, and vice-versa.
3203 * @param toKey high endpoint (exclusive) of the headMap.
3204 * @return a view of the portion of this map whose keys are
3205 * strictly less than <tt>toKey</tt>.
3206 *
3207 * @throws ClassCastException if <tt>toKey</tt> is not
3208 * compatible with this map's comparator (or, if the map has
3209 * no comparator, if <tt>toKey</tt> does not implement
3210 * <tt>Comparable</tt>).
3211 * @throws IllegalArgumentException if <tt>toKey</tt> is
3212 * outside of the range of this submap.
3213 * @throws NullPointerException if <tt>toKey</tt> is
3214 * <tt>null</tt>.
3215 */
3216 public ConcurrentNavigableMap<K,V> headMap(K toKey) {
3217 if (toKey == null)
3218 throw new NullPointerException();
3219 if (!inOpenRange(toKey))
3220 throw new IllegalArgumentException("key out of range");
3221 return new ConcurrentSkipListSubMap(m, least, toKey);
3222 }
3223
3224 /**
3225 * Returns a view of the portion of this map whose keys are
3226 * greater than or equal to <tt>fromKey</tt>. The returned sorted
3227 * map is backed by this map, so changes in the returned sorted
3228 * map are reflected in this map, and vice-versa.
3229 * @param fromKey low endpoint (inclusive) of the tailMap.
3230 * @return a view of the portion of this map whose keys are
3231 * greater than or equal to <tt>fromKey</tt>.
3232 * @throws ClassCastException if <tt>fromKey</tt> is not
3233 * compatible with this map's comparator (or, if the map has
3234 * no comparator, if <tt>fromKey</tt> does not implement
3235 * <tt>Comparable</tt>).
3236 * @throws IllegalArgumentException if <tt>fromKey</tt> is
3237 * outside of the range of this submap.
3238 * @throws NullPointerException if <tt>fromKey</tt> is
3239 * <tt>null</tt>.
3240 */
3241 public ConcurrentNavigableMap<K,V> tailMap(K fromKey) {
3242 if (fromKey == null)
3243 throw new NullPointerException();
3244 if (!inOpenRange(fromKey))
3245 throw new IllegalArgumentException("key out of range");
3246 return new ConcurrentSkipListSubMap(m, fromKey, fence);
3247 }
3248
3249 /* ---------------- Relational methods -------------- */
3250
3251 /**
3252 * Returns a key-value mapping associated with the least key
3253 * greater than or equal to the given key, or <tt>null</tt> if there is
3254 * no such entry. The returned entry does <em>not</em> support
3255 * the <tt>Entry.setValue</tt> method.
3256 *
3257 * @param key the key.
3258 * @return an Entry associated with ceiling of given key, or <tt>null</tt>
3259 * if there is no such Entry.
3260 * @throws ClassCastException if key cannot be compared with the keys
3261 * currently in the map.
3262 * @throws NullPointerException if key is <tt>null</tt>.
3263 */
3264 public Map.Entry<K,V> ceilingEntry(K key) {
3265 return m.getCeiling(key, least, fence);
3266 }
3267
3268 /**
3269 * Returns a key-value mapping associated with the greatest
3270 * key strictly less than the given key, or <tt>null</tt> if there is no
3271 * such entry. The returned entry does <em>not</em> support
3272 * the <tt>Entry.setValue</tt> method.
3273 *
3274 * @param key the key.
3275 * @return an Entry with greatest key less than the given
3276 * key, or <tt>null</tt> if there is no such Entry.
3277 * @throws ClassCastException if key cannot be compared with the keys
3278 * currently in the map.
3279 * @throws NullPointerException if key is <tt>null</tt>.
3280 */
3281 public Map.Entry<K,V> lowerEntry(K key) {
3282 return m.getLower(key, least, fence);
3283 }
3284
3285 /**
3286 * Returns a key-value mapping associated with the greatest
3287 * key less than or equal to the given key, or <tt>null</tt> if there is no
3288 * such entry. The returned entry does <em>not</em> support
3289 * the <tt>Entry.setValue</tt> method.
3290 *
3291 * @param key the key.
3292 * @return an Entry associated with floor of given key, or <tt>null</tt>
3293 * if there is no such Entry.
3294 * @throws ClassCastException if key cannot be compared with the keys
3295 * currently in the map.
3296 * @throws NullPointerException if key is <tt>null</tt>.
3297 */
3298 public Map.Entry<K,V> floorEntry(K key) {
3299 return m.getFloor(key, least, fence);
3300 }
3301
3302 /**
3303 * Returns a key-value mapping associated with the least
3304 * key strictly greater than the given key, or <tt>null</tt> if there is no
3305 * such entry. The returned entry does <em>not</em> support
3306 * the <tt>Entry.setValue</tt> method.
3307 *
3308 * @param key the key.
3309 * @return an Entry with least key greater than the given key, or
3310 * <tt>null</tt> if there is no such Entry.
3311 * @throws ClassCastException if key cannot be compared with the keys
3312 * currently in the map.
3313 * @throws NullPointerException if key is <tt>null</tt>.
3314 */
3315 public Map.Entry<K,V> higherEntry(K key) {
3316 return m.getHigher(key, least, fence);
3317 }
3318
3319 /**
3320 * Returns a key-value mapping associated with the least
3321 * key in this map, or <tt>null</tt> if the map is empty.
3322 * The returned entry does <em>not</em> support
3323 * the <tt>Entry.setValue</tt> method.
3324 *
3325 * @return an Entry with least key, or <tt>null</tt>
3326 * if the map is empty.
3327 */
3328 public Map.Entry<K,V> firstEntry() {
3329 for (;;) {
3330 ConcurrentSkipListMap.Node<K,V> n = firstNode();
3331 if (!isBeforeEnd(n))
3332 return null;
3333 Map.Entry<K,V> e = n.createSnapshot();
3334 if (e != null)
3335 return e;
3336 }
3337 }
3338
3339 /**
3340 * Returns a key-value mapping associated with the greatest
3341 * key in this map, or <tt>null</tt> if the map is empty.
3342 * The returned entry does <em>not</em> support
3343 * the <tt>Entry.setValue</tt> method.
3344 *
3345 * @return an Entry with greatest key, or <tt>null</tt>
3346 * if the map is empty.
3347 */
3348 public Map.Entry<K,V> lastEntry() {
3349 for (;;) {
3350 ConcurrentSkipListMap.Node<K,V> n = lastNode();
3351 if (n == null || !inHalfOpenRange(n.key))
3352 return null;
3353 Map.Entry<K,V> e = n.createSnapshot();
3354 if (e != null)
3355 return e;
3356 }
3357 }
3358
3359 /**
3360 * Removes and returns a key-value mapping associated with
3361 * the least key in this map, or <tt>null</tt> if the map is empty.
3362 * The returned entry does <em>not</em> support
3363 * the <tt>Entry.setValue</tt> method.
3364 *
3365 * @return the removed first entry of this map, or <tt>null</tt>
3366 * if the map is empty.
3367 */
3368 public Map.Entry<K,V> pollFirstEntry() {
3369 return m.removeFirstEntryOfSubrange(least, fence);
3370 }
3371
3372 /**
3373 * Removes and returns a key-value mapping associated with
3374 * the greatest key in this map, or <tt>null</tt> if the map is empty.
3375 * The returned entry does <em>not</em> support
3376 * the <tt>Entry.setValue</tt> method.
3377 *
3378 * @return the removed last entry of this map, or <tt>null</tt>
3379 * if the map is empty.
3380 */
3381 public Map.Entry<K,V> pollLastEntry() {
3382 return m.removeLastEntryOfSubrange(least, fence);
3383 }
3384
3385 /* ---------------- Submap Views -------------- */
3386
3387 /**
3388 * Returns a set view of the keys contained in this map. The
3389 * set is backed by the map, so changes to the map are
3390 * reflected in the set, and vice-versa. The set supports
3391 * element removal, which removes the corresponding mapping
3392 * from this map, via the <tt>Iterator.remove</tt>,
3393 * <tt>Set.remove</tt>, <tt>removeAll</tt>,
3394 * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does
3395 * not support the <tt>add</tt> or <tt>addAll</tt> operations.
3396 * The view's <tt>iterator</tt> is a "weakly consistent"
3397 * iterator that will never throw {@link
3398 * java.util.ConcurrentModificationException}, and guarantees
3399 * to traverse elements as they existed upon construction of
3400 * the iterator, and may (but is not guaranteed to) reflect
3401 * any modifications subsequent to construction.
3402 *
3403 * @return a set view of the keys contained in this map.
3404 */
3405 public Set<K> keySet() {
3406 Set<K> ks = keySetView;
3407 return (ks != null) ? ks : (keySetView = new KeySetView());
3408 }
3409
3410 class KeySetView extends AbstractSet<K> {
3411 public Iterator<K> iterator() {
3412 return m.subMapKeyIterator(least, fence);
3413 }
3414 public int size() {
3415 return ConcurrentSkipListSubMap.this.size();
3416 }
3417 public boolean isEmpty() {
3418 return ConcurrentSkipListSubMap.this.isEmpty();
3419 }
3420 public boolean contains(Object k) {
3421 return ConcurrentSkipListSubMap.this.containsKey(k);
3422 }
3423 public Object[] toArray() {
3424 Collection<K> c = new ArrayList<K>();
3425 for (Iterator<K> i = iterator(); i.hasNext(); )
3426 c.add(i.next());
3427 return c.toArray();
3428 }
3429 public <T> T[] toArray(T[] a) {
3430 Collection<K> c = new ArrayList<K>();
3431 for (Iterator<K> i = iterator(); i.hasNext(); )
3432 c.add(i.next());
3433 return c.toArray(a);
3434 }
3435 }
3436
3437 /**
3438 * Returns a collection view of the values contained in this
3439 * map. The collection is backed by the map, so changes to
3440 * the map are reflected in the collection, and vice-versa.
3441 * The collection supports element removal, which removes the
3442 * corresponding mapping from this map, via the
3443 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
3444 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
3445 * operations. It does not support the <tt>add</tt> or
3446 * <tt>addAll</tt> operations. The view's <tt>iterator</tt>
3447 * is a "weakly consistent" iterator that will never throw
3448 * {@link java.util.ConcurrentModificationException}, and
3449 * guarantees to traverse elements as they existed upon
3450 * construction of the iterator, and may (but is not
3451 * guaranteed to) reflect any modifications subsequent to
3452 * construction.
3453 *
3454 * @return a collection view of the values contained in this map.
3455 */
3456 public Collection<V> values() {
3457 Collection<V> vs = valuesView;
3458 return (vs != null) ? vs : (valuesView = new ValuesView());
3459 }
3460
3461 class ValuesView extends AbstractCollection<V> {
3462 public Iterator<V> iterator() {
3463 return m.subMapValueIterator(least, fence);
3464 }
3465 public int size() {
3466 return ConcurrentSkipListSubMap.this.size();
3467 }
3468 public boolean isEmpty() {
3469 return ConcurrentSkipListSubMap.this.isEmpty();
3470 }
3471 public boolean contains(Object v) {
3472 return ConcurrentSkipListSubMap.this.containsValue(v);
3473 }
3474 public Object[] toArray() {
3475 Collection<V> c = new ArrayList<V>();
3476 for (Iterator<V> i = iterator(); i.hasNext(); )
3477 c.add(i.next());
3478 return c.toArray();
3479 }
3480 public <T> T[] toArray(T[] a) {
3481 Collection<V> c = new ArrayList<V>();
3482 for (Iterator<V> i = iterator(); i.hasNext(); )
3483 c.add(i.next());
3484 return c.toArray(a);
3485 }
3486 }
3487
3488 /**
3489 * Returns a collection view of the mappings contained in this
3490 * map. Each element in the returned collection is a
3491 * <tt>Map.Entry</tt>. The collection is backed by the map,
3492 * so changes to the map are reflected in the collection, and
3493 * vice-versa. The collection supports element removal, which
3494 * removes the corresponding mapping from the map, via the
3495 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
3496 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
3497 * operations. It does not support the <tt>add</tt> or
3498 * <tt>addAll</tt> operations. The view's <tt>iterator</tt>
3499 * is a "weakly consistent" iterator that will never throw
3500 * {@link java.util.ConcurrentModificationException}, and
3501 * guarantees to traverse elements as they existed upon
3502 * construction of the iterator, and may (but is not
3503 * guaranteed to) reflect any modifications subsequent to
3504 * construction. The <tt>Map.Entry</tt> elements returned by
3505 * <tt>iterator.next()</tt> do <em>not</em> support the
3506 * <tt>setValue</tt> operation.
3507 *
3508 * @return a collection view of the mappings contained in this map.
3509 */
3510 public Set<Map.Entry<K,V>> entrySet() {
3511 Set<Map.Entry<K,V>> es = entrySetView;
3512 return (es != null) ? es : (entrySetView = new EntrySetView());
3513 }
3514
3515 class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
3516 public Iterator<Map.Entry<K,V>> iterator() {
3517 return m.subMapEntryIterator(least, fence);
3518 }
3519 public int size() {
3520 return ConcurrentSkipListSubMap.this.size();
3521 }
3522 public boolean isEmpty() {
3523 return ConcurrentSkipListSubMap.this.isEmpty();
3524 }
3525 public boolean contains(Object o) {
3526 if (!(o instanceof Map.Entry))
3527 return false;
3528 Map.Entry<K,V> e = (Map.Entry<K,V>) o;
3529 K key = e.getKey();
3530 if (!inHalfOpenRange(key))
3531 return false;
3532 V v = m.get(key);
3533 return v != null && v.equals(e.getValue());
3534 }
3535 public boolean remove(Object o) {
3536 if (!(o instanceof Map.Entry))
3537 return false;
3538 Map.Entry<K,V> e = (Map.Entry<K,V>) o;
3539 K key = e.getKey();
3540 if (!inHalfOpenRange(key))
3541 return false;
3542 return m.remove(key, e.getValue());
3543 }
3544 public Object[] toArray() {
3545 Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
3546 for (ConcurrentSkipListMap.Node<K,V> n = firstNode();
3547 isBeforeEnd(n);
3548 n = n.next) {
3549 Map.Entry<K,V> e = n.createSnapshot();
3550 if (e != null)
3551 c.add(e);
3552 }
3553 return c.toArray();
3554 }
3555 public <T> T[] toArray(T[] a) {
3556 Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>();
3557 for (ConcurrentSkipListMap.Node<K,V> n = firstNode();
3558 isBeforeEnd(n);
3559 n = n.next) {
3560 Map.Entry<K,V> e = n.createSnapshot();
3561 if (e != null)
3562 c.add(e);
3563 }
3564 return c.toArray(a);
3565 }
3566 }
3567 }
3568
3569 }