org.snapscript.compile.assemble.ExecutorLinker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap-all Show documentation
Show all versions of snap-all Show documentation
Dynamic scripting for the JVM
package org.snapscript.compile.assemble;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import org.snapscript.core.Context;
import org.snapscript.core.Path;
import org.snapscript.core.link.ExceptionPackage;
import org.snapscript.core.link.FuturePackage;
import org.snapscript.core.link.Package;
import org.snapscript.core.link.PackageLinker;
public class ExecutorLinker implements PackageLinker {
private final ConcurrentMap registry;
private final PackageLinker linker;
private final Executor executor;
public ExecutorLinker(Context context) {
this(context, null);
}
public ExecutorLinker(Context context, Executor executor) {
this.registry = new ConcurrentHashMap();
this.linker = new ProgramLinker(context);
this.executor = executor;
}
@Override
public Package link(Path path, String source) throws Exception {
if(executor != null) {
Executable executable = new Executable(path, source);
FutureTask task = new FutureTask(executable);
FuturePackage result = new FuturePackage(task, path);
if(registry.putIfAbsent(path, result) == null) {
executor.execute(task);
return result;
}
return registry.get(path);
}
return linker.link(path, source);
}
@Override
public Package link(Path path, String source, String grammar) throws Exception {
if(executor != null) {
Executable executable = new Executable(path, source, grammar);
FutureTask task = new FutureTask(executable);
FuturePackage result = new FuturePackage(task, path);
if(registry.putIfAbsent(path, result) == null) {
executor.execute(task);
return result;
}
return registry.get(path);
}
return linker.link(path, source, grammar);
}
private class Executable implements Callable {
private final String grammar;
private final String source;
private final Path path;
public Executable(Path path, String source) {
this(path, source, null);
}
public Executable(Path path, String source, String grammar) {
this.grammar = grammar;
this.source = source;
this.path = path;
}
@Override
public Package call() {
try {
if(grammar != null) {
return linker.link(path, source, grammar);
}
return linker.link(path, source);
} catch(Exception cause) {
return new ExceptionPackage("Could not link '" + path +"'", cause);
}
}
}
}