package linkedlists.lockfree;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicMarkableReference;
import contention.abstractions.AbstractCompositionalIntSet;
/**
* This is a variant of the Harris-Michael algorithm in Java
* as presented in the Chapter 9 of the Art of Multiprocessor
* Programming by Herlihy and Shavit.
*
* @author Vincent Gramoli
*
*/
public class NonBlockingLinkedListSet extends AbstractCompositionalIntSet {
private final Node tail;
private final Node head;
public NonBlockingLinkedListSet() {
tail = new Node(Integer.MAX_VALUE, null);
head = new Node(Integer.MIN_VALUE, tail);
}
class Window {
public Node pred, curr;
public Window(Node pred, Node curr) {
this.pred = pred;
this.curr = curr;
}
}
public Window find(Node head, int value) {
Node pred = null, curr = null, succ = null;
boolean[] marked = { false };
boolean snip;
retry: while (true) {
pred = head;
curr = pred.next.getReference();
while (true) {
succ = curr.next.get(marked);
while (marked[0]) {
snip = pred.next.compareAndSet(curr, succ, false, false);
if (!snip) {
continue retry;
}
curr = succ;
succ = curr.next.get(marked);
}
if (curr.value >= value) {
return new Window(pred, curr);
}
pred = curr;
curr = succ;
}
}
}
@Override
public void fill(int range, long size) {
throw new RuntimeException("unimplemented method");
// TODO Auto-generated method stub
}
@Override
public boolean addInt(int x) {
while (true) {
Window window = find(head, x);
Node pred = window.pred, curr = window.curr;
if (curr.value == x) {
return false;
} else {
Node node = new Node(x, curr);
if (pred.next.compareAndSet(curr, node, false, false)) {
return true;
}
}
}
}
@Override
public boolean removeInt(int x) {
boolean snip;
while (true) {
Window window = find(head, x);
Node pred = window.pred, curr = window.curr;
if (curr.value != x) {
return false;
} else {
Node succ = curr.next.getReference();
snip = curr.next.attemptMark(succ, true);
if (!snip) {
continue;
}
pred.next.compareAndSet(curr, succ, false, false);
return true;
}
}
}
@Override
public boolean containsInt(int x) {
boolean[] marked = { false };
Node curr = head;
while (curr.value < x) {
curr = curr.next.getReference();
curr.next.get(marked);
}
return (curr.value == x && !marked[0]);
}
@Override
public Object getInt(int x) {
throw new RuntimeException("unimplemented method");
// TODO Auto-generated method stub
}
@Override
public boolean addAll(Collection<Integer> c) {
throw new RuntimeException("unimplemented method");
// TODO Auto-generated method stub
}
@Override
public boolean removeAll(Collection<Integer> c) {
throw new RuntimeException("unimplemented method");
// TODO Auto-generated method stub
}
@Override
public int size() {
int size = 0;
boolean[] marked = { false };
for (Node curr = head.next.getReference(); curr != tail;){
curr = curr.next.get(marked);
if (!marked[0]){
size++;
}
}
return size;
}
@Override
public void clear() {
head.next = new AtomicMarkableReference<Node>(tail, false);
}
}