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
* lock-coupling (or hand-over-hand/chain locking)
* as described in:
*
* Ch.9 of "The art of Multiprocessor
* Programming" by Herlihy and Shavit.
*
* @author Vincent Gramoli
*
*/
public class LockCouplingListIntSet 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 LockCouplingListIntSet() {
Node min = new Node(Integer.MIN_VALUE);
Node max = new Node(Integer.MAX_VALUE);
min.setNext(max);
head = min;
}
public boolean addInt(int value) {
Node pred = head;
head.lock();
try {
Node curr = pred.getNext();
curr.lock();
try {
while(curr.getValue() < value) {
pred.unlock();
pred = curr;
curr = curr.getNext();
curr.lock();
}
if (curr.getValue() == value) {
return false;
}
Node newNode = new Node(value, curr);
pred.setNext(newNode);
return true;
} finally {
curr.unlock();
}
} finally {
pred.unlock();
}
}
public boolean removeInt(int value) {
Node pred = null;
Node curr = null;
head.lock();
try {
pred = head;
curr = pred.getNext();
curr.lock();
try {
while (curr.getValue() < value) {
pred.unlock();
pred = curr;
curr = curr.getNext();
curr.lock();
}
if (curr.getValue() == value) {
pred.setNext(curr.getNext());
return true;
}
return false;
} finally {
curr.unlock();
}
} finally {
pred.unlock();
}
}
public boolean containsInt(int value) {
Node pred = head;
head.lock();
try {
Node curr = pred.getNext();
curr.lock();
try {
while(curr.getValue() < value) {
pred.unlock();
pred = curr;
curr = curr.getNext();
curr.lock();
}
if (curr.getValue() == value) {
return true;
} else return false;
} finally {
curr.unlock();
}
} finally {
pred.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 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();
}
}