/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: LockFreeSkipList.java * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.util.concurrent.datastructures; import java.util.concurrent.atomic.AtomicMarkableReference; import com.sun.electric.tool.util.concurrent.runtime.MultiThreadedRandomizer; /** * @author Felix Schmidt * */ @Deprecated public class LockFreeSkipList<T> extends IStructure<T> { private static final int MAX_LEVEL = 4; private MultiThreadedRandomizer randomizer; private final Node<T> head = new Node<T>(Integer.MAX_VALUE); @SuppressWarnings("unused") private final Node<T> tail = new Node<T>(Integer.MAX_VALUE); public LockFreeSkipList() { randomizer = new MultiThreadedRandomizer(0); for (int i = 0; i < head.next.length; i++) { head.next[i] = new AtomicMarkableReference<Node<T>>(null, false); } } /* * (non-Javadoc) * * @see com.sun.electric.tool.util.IStructure#add(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public void add(T item) { int topLevel = randomLevel(); int bottomLevel = 0; Node<T>[] preds = (Node<T>[]) new Node[MAX_LEVEL + 1]; Node<T>[] succs = (Node<T>[]) new Node[MAX_LEVEL + 1]; while (true) { boolean found = find(item, preds, succs); if (!found) { Node<T> newNode = new Node<T>(item, topLevel); for (int level = bottomLevel; level <= topLevel; level++) { Node<T> succ = succs[level]; newNode.next[level].set(succ, false); } Node<T> succ = succs[bottomLevel]; Node<T> pred = preds[bottomLevel]; newNode.next[bottomLevel].set(succ, false); if (!pred.next[bottomLevel].compareAndSet(succ, newNode, false, false)) continue; for (int level = bottomLevel + 1; level <= topLevel; level++) { while (true) { pred = preds[level]; succ = succs[level]; if (pred.next[level].compareAndSet(succ, newNode, false, false)) { break; } find(item, preds, succs); } } return; } else { return; } } } private boolean find(T item, Node<T>[] preds, Node<T>[] succs) { int bottomLevel = 0; int key = item.hashCode(); boolean[] marked = { false }; boolean snip; Node<T> pred = null, curr = null, succ = null; retry: while (true) { pred = head; for (int level = MAX_LEVEL; level >= bottomLevel; level--) { curr = pred.next[level].getReference(); while (true) { succ = curr.next[level].get(marked); while (marked[0]) { snip = pred.next[level].compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = pred.next[level].getReference(); succ = curr.next[level].get(marked); } if(curr.key < key) { pred = curr; curr = succ; } else { break; } } preds[level] = pred; succs[level] = curr; } return (curr.key == key); } } private int randomLevel() { return randomizer.getRandomizer().nextInt(MAX_LEVEL + 1); } /* * (non-Javadoc) * * @see com.sun.electric.tool.util.IStructure#isEmpty() */ @Override public boolean isEmpty() { return false; } /* * (non-Javadoc) * * @see com.sun.electric.tool.util.IStructure#remove() */ @Override public T remove() { return null; } public static final class Node<T> { @SuppressWarnings("unused") private final T value; private final int key; private final AtomicMarkableReference<Node<T>>[] next; @SuppressWarnings("unused") private int topLevel; /** * Constructor for sentinel nodes * * @param key */ @SuppressWarnings("unchecked") public Node(int key) { this.value = null; this.key = key; this.next = (AtomicMarkableReference<Node<T>>[]) new AtomicMarkableReference[MAX_LEVEL + 1]; for (int i = 0; i < next.length; i++) next[i] = new AtomicMarkableReference<Node<T>>(null, false); topLevel = MAX_LEVEL; } /** * Constructor for ordinary nodes * * @param x * @param height */ @SuppressWarnings("unchecked") public Node(T x, int height) { value = x; key = x.hashCode(); this.next = (AtomicMarkableReference<Node<T>>[]) new AtomicMarkableReference[height + 1]; for (int i = 0; i < next.length; i++) next[i] = new AtomicMarkableReference<Node<T>>(null, false); topLevel = height; } } }