monniasza.collects.alloc.SimpleAllocator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of multimachinebuilder Show documentation
Show all versions of multimachinebuilder Show documentation
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);
}
}