eu.lucaventuri.collections.NodeLinkedList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fibry Show documentation
Show all versions of fibry Show documentation
The first Java Actor System supporting fibers from Project Loom
package eu.lucaventuri.collections;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* NodeLinkedList that uses Nodes instead of adding values as the Java lists do.
* As a result, we can add and remove a specific node in O(1), which is our goal.
* This class is not thread safe, and it is intended to be used from a single thread.
* In particular it is used as part of the "receive" functionality, so it is called by the actor, which, by definition, runs on a single thread/fiber.
* Thread safety is achieved using a blocking queue before that.
*/
public class NodeLinkedList implements Iterable {
private Node head;
private Node tail;
@Override
public Iterator iterator() {
return new Iterator() {
private Node cur = head;
@Override
public boolean hasNext() {
return cur != null;
}
@Override
public T next() {
T value = cur.value;
cur = cur.next;
return value;
}
};
}
public Iterable> asNodesIterable() {
return new Iterable>() {
@Override
public Iterator> iterator() {
return new Iterator>() {
private Node cur = head;
@Override
public boolean hasNext() {
return cur != null;
}
@Override
public Node next() {
Node value = cur;
cur = cur.next;
return value;
}
};
}
};
}
public Node removeFirstByValue(T value) {
for (Node node : asNodesIterable()) {
if (node.value != null && node.value.equals(value)) {
remove(node);
return node;
}
}
return null;
}
public boolean ieEmpty() {
return head == null;
}
public static class Node {
public final T value;
private Node next;
private Node prev;
Node(T value) {
this.value = value;
}
}
private void verify() {
//assert (tail.get()==null && head.get() == null) || (tail.get() != null && head.get() != null);
}
public Node addToTail(T value) {
verify();
Node n = new Node<>(value);
Node prevTail = tail;
tail = n;
n.prev = prevTail;
if (prevTail != null) {
prevTail.next = n;
} else
head = n;
verify();
return n;
}
public void remove(Node node) {
verify();
if (head == node)
head = node.next;
if (tail == node)
tail = node.prev;
// TODO: it would be nice to assert that it is part of this list...
if (node.prev != null)
node.prev.next = node.next;
if (node.next != null)
node.next.prev = node.prev;
node.prev = node.next = null;
verify();
}
public Node removeHeadNode() {
verify();
// TODO: it would be nice to assert that it is part of this list...
Node prevHead = head;
if (prevHead == null)
return null;
// Head available
Node newHead = prevHead.next;
head = newHead;
if (newHead != null)
newHead.prev = null;
else
tail = null;
verify();
return prevHead;
}
public T removeHead() {
Node node = removeHeadNode();
return node == null ? null : node.value;
}
public T peekHead() {
Node node = head;
return node == null ? null : node.value;
}
public T peekTail() {
Node node = tail;
return node == null ? null : node.value;
}
List asListFromHead() {
List list = new ArrayList<>();
Node n = head;
while (n != null) {
list.add(n.value);
n = n.next;
}
return list;
}
List asListFromTail() {
List list = new ArrayList<>();
Node n = tail;
while (n != null) {
list.add(n.value);
n = n.prev;
}
return list;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy