Skip to content

Harris's List

Pslydhh edited this page Oct 5, 2017 · 1 revision

package org.psly.concurrent;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class LockFreeLinkedList> {
	
	public LockFreeLinkedList() {
		super();
		this.tail = new Node(null, null);
		this.head = new Node(null, new NodePacket(this.tail, false));
	}
		
	public boolean insert(E e){
		Node node = new Node(e, null);
		Object[] nodes;
		//查找该元素
		for(;;){
			nodes = search(e);
			@SuppressWarnings("unchecked")
			Node left = (Node) nodes[0];
			@SuppressWarnings("unchecked")
			NodePacket leftNext = (NodePacket) nodes[1];
			if(leftNext.node != tail && (leftNext.node.value.compareTo(e) == 0))
				return false;
			node.next = new NodePacket(leftNext.node, false);
			if(left.casNext(leftNext, node, leftNext.deleting))
				return true;
		}
	}
	
	@SuppressWarnings("unchecked")
	public boolean delete(E e){
		Object[] nodes;
		Node left;
		NodePacket leftNext;
		Node right;
		for(;;) {
			nodes = search(e);
			left = (Node) nodes[0];
			leftNext = (NodePacket) nodes[1];
			NodePacket rightNext;
			if((right = leftNext.node) == tail || (right.value.compareTo(e) != 0))
				return false;
			if((!(rightNext = right.next).deleting)
				&& right.casNext(rightNext, rightNext.node, true))
					break;
		}
		if(!left.casNext(leftNext, right.next.node, leftNext.deleting))
			search(e);
		return true;
	}
	
	private Object[] search(E key){
		
		searchAgain: 
		for(;;){
			Node prev = head;
			NodePacket prevNext = head.next;
			Node curNode = prevNext.node;
			/* 1: Find left_node and right_node */
			for(;;){
				if(curNode == tail)
					break;
				if(curNode.next.deleting){
					curNode = curNode.next.node;
					continue;
				}
				if(key.compareTo(curNode.value) <= 0){
					break; 
				} else {
					prev = curNode;
					prevNext = curNode.next;
					curNode = prevNext.node;
				}
			}
			Node rightNode = curNode;
			
			//相邻的两个
			if(prevNext.node == rightNode){
				if((rightNode != tail) && rightNode.next.deleting)
					continue searchAgain;
				else
					return new Object[]{prev, prevNext};
			}
			
			
			//不相邻,将中间的这些通通删除
			if(prev.casNext(prevNext, prevNext = new NodePacket(rightNode, prevNext.deleting))){
				if((rightNode != tail) && rightNode.next.deleting)
					continue searchAgain;
				else
					return new Object[]{prev, prevNext};
			}
		}
		
	}

	public String toString(){
		NodePacket nNext = head.next;
		StringBuilder strBuild = new StringBuilder();
		for(;;){
			if(nNext.node == tail)
				break;
			//获取节点
			Node node = nNext.node;
			strBuild.append(node.value).append("\n");
			nNext = node.next;
		}
		return strBuild.toString();
	}
	
	public int size(){
		NodePacket nNext = head.next;
		int num = 0;
		for(;;){
			if(nNext.node == tail)
				break;
			//获取节点
			Node node = nNext.node;
			++num;
			nNext = node.next;
		}
		return num;
	}
	
	public final Node head;
	public final Node tail;
	
	public static class Node{
		final E value;
		volatile NodePacket next;
		
		private static final sun.misc.Unsafe UNSAFE;
		public Node(E value, NodePacket next) {
			super();
			this.value = value;
			this.next = next;
		}

		private static final long nextOffset;
		
		boolean casNext(NodePacket cmp, Node node, boolean deleting){
			return casNext(cmp, new NodePacket(node, deleting));
		}
		
		boolean casNext(NodePacket cmp, NodePacket val){
			return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
		}
		
		static{
			try{
				UNSAFE = UtilUnsafe.getUnsafe();
				nextOffset = UNSAFE.objectFieldOffset(Node.class.getDeclaredField("next"));
			} catch(Exception e){
				throw new Error(e);
			}
		}
	}
	
	public static class NodePacket{
		final Node node;
		final boolean deleting;
		
		public NodePacket(Node node, boolean deleting) {
			super();
			this.node = node;
			this.deleting = deleting;
		}
		
		public Node getNode() {
			return node;
		}
		
		public boolean isDeleting() {
			return deleting;
		}
	}
	
	private static class UtilUnsafe {
		private UtilUnsafe() {
		}

		/** Fetch the Unsafe. Use With Caution. */
		public static Unsafe getUnsafe() {
			if (UtilUnsafe.class.getClassLoader() == null)
				return Unsafe.getUnsafe();
			try {
				final Field fld = Unsafe.class.getDeclaredField("theUnsafe");
				fld.setAccessible(true);
				return (Unsafe) fld.get(UtilUnsafe.class);
			} catch (Exception e) {
				throw new RuntimeException("Could not obtain access to sun.misc.Unsafe", e);
			}
		}
	}
}
Clone this wiki locally