1 /*
 2  * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
 3  */
 4 
 5 package org.openjdk.bench.valhalla.sandbox.corelibs.corelibs;
 6 
 7 import java.util.ConcurrentModificationException;
 8 import java.util.NoSuchElementException;
 9 
10 /**
11  * An inline cursor is a reference to an existing or non-existent element
12  * of a collection.
13  * <p>
14  * Cursor values are immutable, the reference to an element
15  * does not change but the state of the collection can change
16  * so the element is no longer accessible.
17  * Calling {@link #get()} throws a {@link ConcurrentModificationException}.
18  * Iterating through a Collection proceeds by creating new Cursor
19  * from the Collection or advancing to the next or retreating to previous elements.
20  * Advancing past the end of the Collection or retreating before the beginning
21  * results in Cursor values that are non-existent.
22  * A Cursor for an empty Collection does not refer to an element and
23  * throws {@link NoSuchElementException}.
24  * Modifications to the Collection invalidate every Cursor that was created
25  * before the modification.
26  * The typical traversal pattern is:
27  * <pre>{@code
28  *  Collection<T> c = ...;
29  *  for (var cursor = c.cursor(); cursor.exists(); cursor = cursor.advance()) {
30  *      var el = cursor.get();
31  *  }
32  * }
33  * </pre>
34  * <p>
35  * Cursors can be used to {@link #remove()} remove an element from the collection.
36  * Removing an element modifies the collection making that cursor invalid.
37  * The cursor returned from the {@link #remove()} method is a placeholder
38  * for the position, the element occupied, between the next and previous elements.
39  * It can be moved to the next or previous element to continue the iteration.
40  * <p>
41  * The typical traversal and remove pattern follows; when an element is
42  * removed, the cursor returned from the remove is used to continue the iteration:
43  * <pre>{@code
44  *  Collection<T> c = ...;
45  *  for (var cursor = c.cursor(); cursor.exists(); cursor = cursor.advance()) {
46  *      var el = cursor.get();
47  *      if (el.equals(...)) {
48  *          cursor = cursor.remove();
49  *      }
50  *  }
51  * }
52  * </pre>
53  * <p>
54  * @param <T> the type of the element.
55  */
56 public interface InlineCursor<T> {
57     /**
58      * Return true if the Cursor refers to an element.
59      *
60      * If the collection has been modified since the Cursor was created
61      * the element can not be known to exist.
62      * This method does not throw {@link ConcurrentModificationException}
63      * if the collection has been modified but returns false.
64      *
65      * @return  true if this Cursor refers to an element in the collection and
66      *          the collection has not been modified since the cursor was created;
67      *          false otherwise
68      */
69     boolean exists();
70 
71     /**
72      * Return a Cursor for the next element after the current element.
73      * If there is no element following this element the returned
74      * Cursor will be non-existent. To wit: {@code Cursor.exists() == false}.
75      *
76      * @return return a cursor for the next element after this element
77      * @throws ConcurrentModificationException if the collection
78      *         has been modified since this Cursor was created
79      */
80     InlineCursor<T> advance();
81 
82     /**
83      * Return the current element referred to by the Cursor.
84      *
85      * The behavior must be consistent with {@link #exists()}
86      * as long as the collection has not been modified.
87      *
88      * @return  return the element in the collection if the collection
89      *          has not been modified since the cursor was created
90      * @throws NoSuchElementException if the referenced element does not exist
91      *         or no longer exists
92      * @throws ConcurrentModificationException if the collection
93      *         has been modified since this Cursor was created
94      */
95     T get();
96 }