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

monniasza.collects.alloc.SimpleAllocator Maven / Gradle / Ivy

Go to download

Dependency for the MultiMachineBuilder, a voxel game about building an industrial empire in a finite world. THIS RELEASE IS NOT PLAYABLE. To play the game, donwload from >ITCH.IO LINK HERE< or >GH releases link here<

The newest version!
/**
 * 
 */
package monniasza.collects.alloc;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;

import com.google.common.collect.Iterators;

import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntIterator;
import it.unimi.dsi.fastutil.ints.IntList;

/**
 * @author oskar
 * @param  
 * An implementation of the allocator.
 * Exceptions thrown by listeners are forwarded to the {@code exceptionHandler} object in this allocator
 * The {@code exceptionHandler} by default forwards exceptions to the thread's current UncaughtExceptionHandler, where thread is the thread used to run listeners
 */
public class SimpleAllocator implements Allocator {
	
	private Consumer exceptionHandler = (ex -> {
		UncaughtExceptionHandler ueh = Thread.currentThread().getUncaughtExceptionHandler();
		if(ueh != null) ueh.uncaughtException(Thread.currentThread(), ex);
	});

	private ArrayList data = new ArrayList<>();
	private IntList free = new IntArrayList();
	
	private class Node{
		Node(T value) {
			super();
			this.value = value;
		}
		T value() {
			return value;
		}
		final T value;
		List> nodeListeners = new ArrayList<>();
	}
	
	@Override
	public int allocate(T obj) {
		Node node = new Node(obj);
		int next;
		if(free.isEmpty()) {
			//Generate new values
			next = data.size();
			data.add(node);
		}else {
			//Reuse the value
			IntIterator iterator = free.intIterator();
			next = iterator.nextInt();
			iterator.remove();
			data.set(next, node);
		}		
		for(AllocationListener listener: listeners) {
			try {
				listener.allocated(next, obj);
			}catch(Exception e) {
				exceptionHandler.accept(e);
			}
		}
		return next;
	}

	@Override
	public void destroy(int id) {
		if(!isAllocated(id)) throw new NoSuchElementException("Index "+id+" does not exist");
		Node result = data.get(id);
		T value = null;
		if(result != null) value = result.value;
		
		for(AllocationListener listener: listeners) {
			try {
				listener.deallocated(id, value);
			}catch(Exception e) {
				exceptionHandler.accept(e);
			}
		}
		if(result != null) for(AllocationListener listener: result.nodeListeners) {
			try {
				listener.deallocated(id, value);
			}catch(Exception e) {
				exceptionHandler.accept(e);
			}
		}
		free.add(id);
		data.set(id, null);
	}

	private List> listeners = new ArrayList<>();
	@Override
	public void addAllocationListener(AllocationListener listener) {
		listeners.add(listener);
	}

	@Override
	public void removeAllocationListener(AllocationListener listener) {
		listeners.remove(listener);
	}

	@Override
	public void addSpecificAllocationListener(AllocationListener listener, int index) {
		Node result = data.get(index);
		if(result != null) result.nodeListeners.add(listener);
	}

	@Override
	public void removeSpecificAllocationListener(AllocationListener listener, int index) {
		Node result = data.get(index);
		if(result != null) result.nodeListeners.remove(listener);
	}

	/**
	 * @return current exception handler
	 */
	public Consumer getExceptionHandler() {
		return exceptionHandler;
	}

	/**
	 * @param exceptionHandler new exception handler
	 */
	public void setExceptionHandler(Consumer exceptionHandler) {
		this.exceptionHandler = exceptionHandler;
	}

	@Override
	public boolean isAllocated(int id) {
		if(id >= data.size()) return false;
		return data.get(id) != null;
	}

	@Override
	public T get(int id) {
		Node result = data.get(id);
		if(result == null) return null;
		return result.value;
	}

	@Override
	public int size() {
		return data.size();
	}

	@SuppressWarnings("null")
	@Override
	public Iterator iterator() {
		return Iterators.transform(Iterators.filter(data.iterator(), Objects::nonNull), Node::value);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy