All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.summerb.utils.collection.OneWayList Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
package org.summerb.utils.collection;

import java.util.Iterator;

import com.google.common.base.Preconditions;

/**
 * This is one way linked list intended for use in concurrent scenarios where we
 * try to avoid using locking (lock-free algorithms). It is not completely lock
 * free, but at least for read it's lock free.
 * 
 * @author sergeyk
 *
 * @param 
 */
public class OneWayList implements Iterable {
	private volatile Entry first;
	private volatile Entry last;

	private Object syncRoot = new Object();

	public OneWayList() {

	}

	public boolean isEmpty() {
		return first == null;
	}

	public T getFirst() {
		Entry f = first;
		return f == null ? null : f.data;
	}

	public T getLast() {
		Entry l = last;
		return l == null ? null : l.data;
	}

	@Override
	public OneWayIterator iterator() {
		return new OneWayIterator(first);
	}

	public void append(T data) {
		Entry newEntry = new Entry(data);
		if (first == null) {
			first = last = newEntry;
			return;
		}

		Entry curLast = last;
		last = newEntry;
		curLast.next = newEntry;
	}

	public void appendThreadSafe(T data) {
		synchronized (syncRoot) {
			append(data);
		}
	}

	public class OneWayIterator implements Iterator {
		private Entry current;
		private Entry startingElement;
		private Entry prevCur;

		public OneWayIterator(Entry first) {
			this.startingElement = first;
		}

		@Override
		public boolean hasNext() {
			Entry cur = getCurrent();
			if (cur == null) {
				return startingElement != null;
			}

			return cur.next != null;
		}

		@Override
		public T next() {
			if (!hasNext()) {
				throw new IndexOutOfBoundsException("No more elements");
			}

			Entry cur = getCurrent();
			if (cur == null) {
				setCurrent(startingElement);
				return startingElement.data;
			}

			Entry next = cur.next;
			setCurrent(next);
			return next.data;
		}

		public void shiftListHead() {
			Entry cur = getCurrent();
			if (cur == null) {
				throw new IndexOutOfBoundsException("No more elements");
			}

			OneWayList.this.first = (Entry) cur;
		}

		public void insertNewBeforeCurrent(T newItem) {
			Preconditions.checkState(current != null, "Cannot insertNewBeforeCurrent for iteration that not started");

			Entry e = new Entry(newItem);
			e.next = current;

			if (prevCur == null) {
				// ok, this is new first item
				first = e;
			} else {
				// ok, inserted item in the middle
				prevCur.next = e;
			}
		}

		@Override
		public void remove() {
			throw new IllegalStateException("Remove operation is not supported by OneWayList");
		}

		private Entry getCurrent() {
			return current;
		}

		private void setCurrent(Entry cur) {
			prevCur = this.current;
			this.current = cur;
		}
	}

	private static class Entry {
		T data;
		volatile Entry next;

		public Entry(T data) {
			this.data = data;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy