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

xapi.collect.impl.SimpleFifo Maven / Gradle / Ivy

Go to download

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;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy