package linkedlists.lockbased;
import java.util.Collection;
import java.util.Random;
import java.util.Stack;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import contention.abstractions.CompositionalIntSet;
import contention.abstractions.CompositionalIterator;
/**
* Linked list implementation of integer set using
* optimistic locking as described in:
*
* Ch.9 of "The art of Multiprocessor
* Programming" by Herlihy and Shavit.
*
* @author Francesco Zappa Nardelli
*
*/
public class OptimisticListSortedSet implements CompositionalIntSet {
/** The first node of the list */
final private Node head;
/** The thread-private PRNG */
final private static ThreadLocal<Random> s_random = new ThreadLocal<Random>() {
@Override
protected synchronized Random initialValue() {
return new Random();
}
};
public OptimisticListSortedSet() {
Node min = new Node(Integer.MIN_VALUE);
Node max = new Node(Integer.MAX_VALUE);
min.setNext(max);
head = min;
}
private boolean validate(Node pred, Node curr) {
Node node = head;
while (node.getValue() <= pred.getValue()) {
if (node == pred)
return pred.getNext() == curr;
node = node.getNext();
}
return false;
}
public boolean addInt(int value) {
while (true) {
Node pred = head;
Node curr = pred.getNext();
while (curr.getValue() < value) {
pred = curr;
curr = curr.getNext();
}
pred.lock();
curr.lock();
try {
if (validate(pred,curr)) {
if (curr.getValue() == value) {
return false;
} else {
Node node = new Node(value, curr);
pred.setNext(node);
return true;
}
}
} finally {
pred.unlock();
curr.unlock();
}
}
}
public boolean removeInt(int value) {
while (true) {
Node pred = head;
Node curr = pred.getNext();
while (curr.getValue() < value) {
pred = curr;
curr = curr.getNext();
}
pred.lock();
curr.lock();
try {
if (validate(pred,curr)) {
if (curr.getValue() == value) {
pred.setNext(curr.getNext());
return true;
} else {
return false;
}
}
} finally {
pred.unlock();
curr.unlock();
}
}
}
public boolean containsInt(int value) {
while (true) {
Node pred = head;
Node curr = pred.getNext();
while (curr.getValue() < value) {
pred = curr;
curr = curr.getNext();
}
/*pred.lock();
curr.lock();
try {
if (validate(pred,curr)) {*/
return (curr.getValue() == value);
/*}
} finally {
pred.unlock();
curr.unlock();
}*/
}
}
/**
* This method cannot be supported with
* such locking mechanism
*/
@Override
public boolean addAll(Collection<Integer> c) {
throw new UnsupportedOperationException();
}
/**
* This method cannot be supported with
* such locking mechanism
*/
@Override
public boolean removeAll(Collection<Integer> c) {
throw new UnsupportedOperationException();
}
/**
* This method is not thread-safe. It cannot
* be made atomic with such locking mechanism
*/
public int size() {
int n = 0;
Node node = head;
while (node.getNext().getValue() < Integer.MAX_VALUE) {
n++;
node = node.getNext();
}
return n;
}
@Override
public void fill(final int range, final long size) {
while (this.size() < size) {
this.addInt(s_random.get().nextInt(range));
}
}
public class Node {
final private int value;
private volatile Node next;
final private Lock lock;
public Node(int value, Node next) {
this.value = value;
this.next = next;
this.lock = new ReentrantLock();
}
public Node(int value) {
this(value, null);
}
public int getValue() {
return value;
}
public void setNext(Node next) {
this.next = next;
}
public Node getNext() {
return next;
}
public void lock() {
this.lock.lock();
}
public void unlock() {
this.lock.unlock();
}
}
// public class LLIterator implements CompositionalIterator<Integer> {
// Node next = head;
// Stack<Node> stack = new Stack<Node>();
// LLIterator() {
// while (next != null) {
// stack.push(next.next);
// }
// }
// public boolean hasNext() {
// return next != null;
// }
// public void remove() {
// throw new UnsupportedOperationException();
// }
// public Integer next() {
// Node node = next;
// next = stack.pop();
// return node.getValue();
// }
// }
public void clear() {
Node max = new Node(Integer.MAX_VALUE);
head.setNext(max);
}
@Override
public Object getInt(int x) {
throw new UnsupportedOperationException();
}
@Override
public Object putIfAbsent(int x, int y) {
throw new UnsupportedOperationException();
}
}