package skiplists.transactional; import java.util.Collection; import java.util.Random; import java.util.Stack; import java.lang.String; import org.deuce.Atomic; import contention.abstractions.CompositionalIntSet; import contention.abstractions.CompositionalIterator; /** * The Transactional Skip List implementation of integer set * @author Vincent Gramoli * */ public class CompositionalSkipListIntSet implements CompositionalIntSet { /** The maximum number of levels */ final private int maxLevel; /** The first element of the list */ final public Node head; /** The thread-private PRNG, used for fil(), not for height/level determination. */ final private static ThreadLocal<Random> s_random = new ThreadLocal<Random>() { @Override protected synchronized Random initialValue() { return new Random(); } }; public CompositionalSkipListIntSet() { this(31); } public CompositionalSkipListIntSet(final int maxLevel) { this.maxLevel = maxLevel; this.head = new Node(maxLevel, Integer.MIN_VALUE); final Node tail = new Node(maxLevel, Integer.MAX_VALUE); for (int i = 0; i <= maxLevel; i++) { head.setNext(i, tail); } } public void fill(final int range, final long size) { while (this.size() < size) { this.addInt(s_random.get().nextInt(range)); } } protected int randomLevel() { return Math.min((maxLevel - 1), (skiplists.RandomLevelGenerator.randomLevel())); } @Override @Atomic(metainf = "elastic") public boolean containsInt(final int value) { boolean result; Node node = head; for (int i = maxLevel; i >= 0; i--) { Node next = node.getNext(i); while (next.getValue() < value) { node = next; next = node.getNext(i); } } node = node.getNext(0); result = (node.getValue() == value); return result; } @Override @Atomic(metainf = "elastic") public boolean addInt(final int value){ boolean result; Node[] update = new Node[maxLevel + 1]; Node node = head; for (int i = maxLevel; i >= 0; i--) { Node next = node.getNext(i); while (next.getValue() < value) { node = next; next = node.getNext(i); } update[i] = node; } node = node.getNext(0); if (node.getValue() == value) { result = false; } else { int level = randomLevel(); node = new Node(level, value); for (int i = 0; i <= level; i++) { node.setNext(i, update[i].getNext(i)); update[i].setNext(i, node); } result = true; } return result; } @Override @Atomic(metainf = "elastic") public boolean removeInt(int value) { boolean result; Node[] update = new Node[maxLevel + 1]; Node node = head; for (int i = maxLevel; i >= 0; i--) { Node next = node.getNext(i); while (next.getValue() < value) { node = next; next = node.getNext(i); } update[i] = node; } node = node.getNext(0); if (node.getValue() != value) { result = false; } else { int maxLevel = node.getLevel(); for (int i = 0; i <= maxLevel; i++) { update[i].setNext(i, node.getNext(i)); } result = true; } return result; } @Override @Atomic(metainf = "elastic") public boolean addAll(Collection<Integer> c) { boolean result = true; for (int x : c) result &= this.addInt(x); return result; } @Override @Atomic(metainf = "elastic") public boolean removeAll(Collection<Integer> c) { boolean result = true; for (int x : c) result &= this.removeInt(x); return result; } @Override @Atomic(metainf = "roregular") public int size() { int s = 0; Node node = head.getNext(0).getNext(0); while (node != null) { node = node.getNext(0); s++; } return s; } @Override public String toString() { String str = new String(); Node curr = head; int i, j; final int[] arr = new int[maxLevel+1]; for (i=0; i<= maxLevel; i++) arr[i] = 0; do { str += curr.toString(); arr[curr.getLevel()]++; curr = curr.getNext(0); } while (curr != null); for (j=0; j < maxLevel; j++) str += arr[j] + " nodes of level " + j; return str; } public class Node { final private int value; final private Node[] next; public Node(final int level, final int value) { this.value = value; next = new Node[level + 1]; } public int getValue() { return value; } public int getLevel() { return next.length - 1; } public void setNext(final int level, final Node succ) { next[level] = succ; } public Node getNext(final int level) { return next[level]; } @Override public String toString() { String result = ""; result += "<l=" + getLevel() + ",v=" + value + ">:"; for (int i = 0; i <= getLevel(); i++) { result += " @[" + i + "]="; if (next[i] != null) { result += next[i].getValue(); } else { result += "null"; } } return result; } } public class SLIterator implements CompositionalIterator<Integer> { Node next = head; Stack<Node> stack = new Stack<Node>(); SLIterator() { while (next != null) { stack.push(next.next[0]); } } public boolean hasNext() { return next != null; } public void remove() { throw new UnsupportedOperationException(); } public Integer next() { Node node = next; next = stack.pop(); return node.getValue(); } } /** * This is called after the JVM warmup phase * to make sure the data structure is well initalized. * No need to do anything for this. */ public void clear() { return; } @Atomic(metainf = "elastic") public Object getInt(int value) { Node node = head; for (int i = maxLevel; i >= 0; i--) { Node next = node.getNext(i); while (next.getValue() < value) { node = next; next = node.getNext(i); } } node = node.getNext(0); if (node.getValue() == value) return node; return null; } @Atomic(metainf = "regular") public Object putIfAbsent(int x, int y) { if (!containsInt(x)) addInt(y); return null; } }