xapi.collect.impl.SimpleFifo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-gwt Show documentation
Show all versions of xapi-gwt Show documentation
This module exists solely to package all other gwt modules into a single
uber jar. This makes deploying to non-mavenized targets much easier.
Of course, you would be wise to inherit your dependencies individually;
the uber jar is intended for projects like collide,
which have complex configuration, and adding many jars would be a pain.
The newest version!
package xapi.collect.impl;
import java.io.Serializable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import xapi.annotation.inject.InstanceDefault;
import xapi.collect.api.Fifo;
import xapi.util.api.ConvertsValue;
/**
* A simple, fast, threadsafe, one-way, single-linked list.
*
* This primitive collection eats nulls (ignores them on add),
* it will only return null from take() when it is empty,
* and it handles concurrency by synchronizing on a single object for the
* whole collection. A read in the middle of a write might get missed if
* the timing is very close, but no reads will be missed it you call take()
* until the fifo is drained.
*
* @author "James X. Nelson ([email protected])"
*
* @param - The type of item stores in the fifo
*/
@InstanceDefault(implFor=Fifo.class)
public class SimpleFifo implements Fifo, Iterable, Serializable{
private static final long serialVersionUID = 2525421548842680240L;
private class Itr implements Iterator {
Node last = head, node = last;
@Override
public boolean hasNext() {
return node.next != null;
}
@Override
public E next() {
last = node;
node = node.next;
if (node == null)
throw new NoSuchElementException();
return node.item;
}
@Override
public void remove() {
Node expected = node;
synchronized(head) {
if (last.next != expected)
return;
if (node == tail)
tail = last;
if (last == node) {
if (last == head)
throw new IllegalStateException();
return;
}
last.next = node.next;
node.next = null;//help gc
node = last;
size--;
}
}
}
@Override
public boolean contains(E item) {
for (E e : forEach())
if (equals(item,e))
return true;
return false;
}
protected final class Node implements Serializable {
private static final long serialVersionUID = -4821223918445216546L;
public E item;
public Node next;
@Override
public String toString() {
return String.valueOf(item);
}
}
protected Node head = new Node();
private transient Node tail;
private int size;
public SimpleFifo() {
tail = head;
}
public SimpleFifo(E[] els) {
this();
for (E el : els) {
if (el == null) {
return;
}
give(el);
}
}
@Override
public Fifo give(E item) {
if (item==null)return this;
Node add = new Node();
add.item = item;
synchronized (head) {
size++;
tail.next = add;
tail = add;
}
return this;
}
@Override
public void clear() {
head.next = null;
tail = head;
size = 0;
}
@Override
public boolean remove(E item) {
Node start = head, next = head.next;
int was;
synchronized(head) {
was = size;
while (next != null) {
if (equals(next.item, item)) {
size--;
if (next == tail) {
tail = start;
tail.next = null;
} else {
start.next = next.next;
}
next.next = null;//help gc
next = start.next;
}else {
start = next;
next = next.next;
}
}
}
return was>size;
}
protected boolean equals(E one, E two) {
return one.equals(two);
}
@Override
public E take() {
synchronized (head) {
Node next = head.next;
if (next == null) {
tail = head;
return null;
}
size--;
head.next = next.next;
if (next == tail)
tail = head;
try {
return next.item;
}finally {
//drop all unneeded references!
next.item = null;
}
}
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return head == tail;
}
@Override
protected void finalize() throws Throwable {
synchronized (head) {
head.next = null;
tail = null;
}
}
@Override
public String toString() {
return " ["+head.next +" -> "+tail+"]";
}
@Override
public Iterator iterator() {
return new Itr();
}
@Override
public Iterable forEach() {
return this;
}
@Override
public String join(String delim) {
Node n = head.next;
if (n == null)return "";
StringBuilder b = new StringBuilder();
b.append(n.item);
while ((n = n.next)!=null) {
b.append(delim);
b.append(n.item);
}
return b.toString();
}
public String join(String delim, ConvertsValue serializer) {
Node n = head.next;
if (n == null)return "";
StringBuilder b = new StringBuilder();
b.append(serialize(serializer, n.item));
while ((n = n.next)!=null) {
b.append(delim);
b.append(serializer.convert(n.item));
}
return b.toString();
}
protected String serialize(ConvertsValue serializer, E item) {
return serializer == null ? String.valueOf(item) : serializer.convert(item);
}
@Override
@SuppressWarnings("unchecked")
public Fifo giveAll(E ... elements) {
for (E element : elements)
give(element);
return this;
}
@Override
public Fifo giveAll(Iterable elements) {
for (E element : elements)
give(element);
return this;
}
}