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 Show documentation
Show all versions of snap 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, executor);
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);
}
}
}
}