/******************************************************************************
* Copyright (c) 2009 - 2015 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package data.concurrent;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
final public class HarrisList {
final private Node head;
final private Node tail;
public HarrisList() {
super();
head = new Node(Short.MIN_VALUE);
tail = new Node(Short.MAX_VALUE);
head.next.set(tail);
}
public boolean insert(int key) {
Node newNode = new Node(key);
Node rightNode;
Node leftNode;
do {
Pair pair = this.search(key);
leftNode = pair.fst;
rightNode = pair.snd;
if (rightNode != tail && rightNode.key == key) { return false; }
newNode.next = new AtomicReference(rightNode);
if (leftNode.next.compareAndSet(rightNode, newNode)) return true;
}while(true);
}
public boolean delete(int key) {
Node rightNode;
Node rightNodeNext;
Node leftNode;
do {
Pair pair = this.search(key);
leftNode = pair.fst;
rightNode = pair.snd;
if (rightNode == tail || rightNode.key != key) { return false; }
rightNodeNext = rightNode.next();
if (!rightNode.isMarked()) {
if (rightNode.isMarked.compareAndSet(false, true)) { break; }
}
}while(true);
if (!leftNode.next.compareAndSet(rightNode, rightNodeNext)) {
this.search(rightNode.key);
}
return true;
}
private Pair search(int searchKey) {
Node leftNode = null;
Node leftNodeNext = null;
Node rightNode = null;
search_again: do {
Node t = head;
Node tNext = head.next();
do {
if (!t.isMarked.get()) {
leftNode = t;
leftNodeNext = t.next();
}
t = tNext;
if (t == tail) break;
tNext = t.next();
}while(t.isMarked() || t.key < searchKey);
rightNode = t;
if (leftNodeNext == rightNode) {
if (rightNode != tail && rightNode.isMarked())
continue search_again;
else return new Pair(leftNode, rightNode);
}
if (leftNode.next.compareAndSet(leftNodeNext, rightNode)) {
if (rightNode != tail && rightNode.isMarked())
continue search_again;
else return new Pair(leftNode, rightNode);
}
}while(true);
}
final private static class Node {
int key;
AtomicReference next;
AtomicBoolean isMarked;
Node(int key) {
super();
this.key = key;
this.next = new AtomicReference();
this.isMarked = new AtomicBoolean(false);
}
boolean isMarked() { return isMarked.get(); }
Node next() { return (Node) next.get(); }
}
final private static class Pair {
final Node fst;
final Node snd;
Pair(Node fst, Node snd) {
super();
this.fst = fst;
this.snd = snd;
}
}
}