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

javaxt.utils.Generator Maven / Gradle / Ivy

package javaxt.utils;

import java.util.Iterator;
import java.util.NoSuchElementException;

//******************************************************************************
//**  Generator
//******************************************************************************
/**
 * A custom iterator that yields its values one at a time. This is a great
 * alternative to arrays or lists when dealing with large data. By yielding one
 * entry at a time, this iterator can help avoid out of memory exceptions.
 *
 * Subclasses must define a method called {@link #run()} and may call
 * {@link yield(T)} to return values one at a time. Example:
 * 
 * 
 * Generator<String> generator = new Generator<String>() {
 * 
 * 	@Override
 * 	public void run() {
 * 
 * 		BufferedReader br = file.getBufferedReader("UTF-8");
 * 
 * 		String row;
 * 		while ((row = br.readLine()) != null) {
 * 			yield(row);
 * 		}
 * 
 * 		br.close();
 * 	}
 * };
 * 
* * @author Adrian Kuhn <akuhn(at)iam.unibe.ch> * ******************************************************************************/ public abstract class Generator implements Iterable { public abstract void run(); @Override public Iterator iterator() { return new Iter(); } private static final Object DONE = new Object(); private static final Object EMPTY = new Object(); private Object drop = EMPTY; private Thread th = null; private synchronized Object take() { while (drop == EMPTY) { try { wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } Object temp = drop; if (drop != DONE) drop = EMPTY; notifyAll(); return temp; } private synchronized void put(Object value) { if (drop == DONE) throw new IllegalStateException(); if (drop != EMPTY) throw new IllegalStateException(); drop = value; notifyAll(); while (drop != EMPTY) { try { wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } protected void yield(T value) { put(value); } public synchronized void done() { if (drop == DONE) throw new IllegalStateException(); if (drop != EMPTY) throw new IllegalStateException(); drop = DONE; notifyAll(); } private class Iter implements Iterator, Runnable { private Object next = EMPTY; public Iter() { if (th != null) throw new IllegalStateException("Can not run coroutine twice"); th = new Thread(this); th.setDaemon(true); th.start(); } @Override public void run() { Generator.this.run(); done(); } @Override public boolean hasNext() { if (next == EMPTY) next = take(); return next != DONE; } @Override @SuppressWarnings("unchecked") public T next() { if (next == EMPTY) next = take(); if (next == DONE) throw new NoSuchElementException(); Object temp = next; next = EMPTY; return (T) temp; } @Override public void remove() { throw new UnsupportedOperationException(); } @SuppressWarnings("deprecation") @Override protected void finalize() throws Throwable { th.stop(); // let's commit suicide } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy